Compare commits

..

571 Commits

Author SHA1 Message Date
9eb89e0411 bump version to 1.0.31 2025-09-07 07:40:09 +04:00
5fcdadcabd bump version to 1.0.30 2025-09-07 07:30:48 +04:00
d542d080fa ... 2025-09-07 07:30:09 +04:00
f6557335ee ... 2025-09-07 07:23:43 +04:00
bbac841427 ... 2025-09-07 07:21:40 +04:00
746d9d16c7 Merge branch 'development' into development_herorun
* development:
  ...
  bump version to 1.0.30
2025-09-07 07:02:09 +04:00
075b6bd124 ... 2025-09-05 14:13:39 +04:00
9174e60d78 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-09-05 14:07:20 +04:00
85b17eeb05 bump version to 1.0.30 2025-09-05 14:07:16 +04:00
Mahmoud-Emad
8d03eb822d feat: add HeroRun remote container management library
- Introduce Executor for remote container orchestration
- Add Container lifecycle management with tmux
- Support Alpine and Alpine Python base images
- Auto-install core dependencies on remote node
- Include full usage examples and updated README
2025-09-03 18:32:47 +03:00
Mahmoud-Emad
0ee57a8075 test: update logger instantiation in test 2025-09-03 11:44:34 +03:00
Mahmoud-Emad
dd400ba6fa style: improve code formatting; refactor module imports
- Apply consistent alignment for struct fields and parameters
- Standardize string literal delimiters to single quotes
- Refactor module import strategy in `models` package
- Enhance asset formatting for precise decimal display
- Remove unused imports and redundant `+}` syntax artifacts
2025-09-03 11:36:02 +03:00
Mahmoud-Emad
4a82bde192 refactor: migrate to redisclient and update V-lang syntax
- Refactor Redis client usage to `herolib.core.redisclient`
- Improve Redis connection error handling and logging
- Update V-lang syntax: string interpolation, `spawn`, key generation
- Expose `herocluster` types and methods as public
- Add `redisclient` usage example in `escalayer` module
2025-09-03 11:22:18 +03:00
Mahmoud-Emad
08bcd3bc56 fix: Fix SSH result for exit code 1 and refactor ping
- Alias `herolib.core` import to `herolib_core`
- Use `herolib_core.platform()` for clarity
- Store `res.output` in `res_output` variable
- Return `res_output` consistently
- Change `SSHResult.tcpport` to `SSHResult.ssh`
2025-09-03 10:41:07 +03:00
Mahmoud-Emad
49bf9dbf80 test: Update ping test assertions
- Use boolean `true` for successful ping
- Use boolean `false` for ping timeout
- Use boolean `false` for unknown host
2025-09-03 10:24:19 +03:00
Omdanii
2b39801164 Merge pull request #142 from freeflowuniverse/development_decartive
test: update ping call parameters in tests
2025-09-03 10:19:18 +03:00
Mahmoud-Emad
5bfaec3cb3 test: update ping call parameters in tests
- Rename `timeout` to `nr_ok` in `addr.ping` calls
- Rename `count` to `retry` in `ping` function calls
- Replace `timeout` with `nr_ok` in `ping` function calls
2025-09-03 10:15:23 +03:00
Omdanii
99427fcbef Merge pull request #141 from freeflowuniverse/development_decartive
Tmux decorative version
2025-09-02 19:34:30 +03:00
Mahmoud-Emad
1bd91cd51a refactor: clean up imports and enhance error handling
- Remove multiple unused imports
- Change `is_running` to return `!bool`
- Update `is_running` calls to handle result type
2025-09-02 19:27:18 +03:00
Mahmoud-Emad
03935c3637 Merge branch 'development' into development_decartive 2025-09-02 19:10:58 +03:00
Mahmoud-Emad
b84e9a046c feat: add declarative tmux pane command management
- Implement Redis-backed command state tracking
- Use MD5 hashing to detect command changes in panes
- Kill and restart pane commands only when necessary
- Ensure bash is the parent process in each pane
- Add pane reset and emptiness checks before command execution
2025-09-02 19:10:34 +03:00
Mahmoud-Emad
b3fe4dd2cd feat: add multi-line command support for tmux panes
- Refactor `send_command` to handle multi-line input
- Implement `send_multiline_command` to execute temp scripts
- Create temporary bash scripts for multi-line commands
- Add documentation and examples for multi-line commands
2025-09-02 16:02:46 +03:00
Mahmoud-Emad
49f15d46bb fix: improve stdin compatibility with tmux pipe-pane
- Replace `io.new_buffered_reader` with raw `os.fd_read`
- Implement manual line buffering for stdin input
- Process any remaining partial line after input stream ends
- Address `tmux pipe-pane` data handling differences
2025-09-02 15:07:14 +03:00
Mahmoud-Emad
cf8e69041d feat: improve tmux_logger with flexible argument parsing
- Add structured argument parsing to `tmux_logger` utility
- Introduce `--no-log` and `--logreset` command-line options
- Enable dynamic log path resolution and pane-specific directories
- Simplify tmux pane logging integration, remove buffer script
- Standardize log category output padding in `categorize_output`
2025-09-02 13:47:35 +03:00
Timur Gordon
89ef8442a3 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-09-02 10:15:03 +02:00
Timur Gordon
9bbe8abd6b rpc fixes 2025-09-02 10:13:55 +02:00
de763f14f6 ... 2025-09-02 09:36:21 +02:00
d5f06ef971 ... 2025-09-02 09:24:49 +02:00
357a9e58ba ... 2025-09-02 09:22:25 +02:00
635950f33a ... 2025-09-02 09:21:26 +02:00
ad71b6943e ... 2025-09-02 09:18:36 +02:00
9beb763c93 Merge branch 'development_decartive' into development
* development_decartive:
  ...
  ...
  ...
  ...
  ...
  ...
  feat: add real-time logging for tmux panes
  ...
  refactor: Migrate from `vweb` to `veb` web framework
  feat: Add robust cross-platform port availability check
  Update the exe path
  chore: remove deprecated tmux example scripts and testing docs
  feat: Implement comprehensive process cleanup for tmux
  feat: implement dynamic pane resizing
  ...
  ...
  feat: Add declarative tmux module functions
2025-09-02 09:10:20 +02:00
40455a8c2e ... 2025-09-02 09:09:21 +02:00
418a38527a ... 2025-09-02 08:52:51 +02:00
3af0aef6c1 ... 2025-09-02 08:44:44 +02:00
c9dc8fb44b Merge branch 'development_decartive' of github.com:freeflowuniverse/herolib into development_decartive 2025-09-02 07:49:16 +02:00
18f4471d3f ... 2025-09-02 07:49:10 +02:00
b0f82ac834 ... 2025-09-02 07:28:13 +02:00
ff1b343a95 ... 2025-09-02 06:54:04 +02:00
ITX Oliver Lienhard
5255006b92 Trigger security scan 2025-09-02 01:58:41 +02:00
ITX Oliver Lienhard
38dd076cb9 Add Github Actions Security workflow 2025-09-02 01:58:39 +02:00
Mahmoud-Emad
52a1d2f80d feat: add real-time logging for tmux panes
- Introduce `tmux_logger` app for categorized output
- Implement pane logging via `tmux pipe-pane`
- Add `log`, `logpath`, `logreset` options to panes
- Update `Pane` struct with logging state and cleanup
- Refactor `logger.new` to use `LoggerFactoryArgs`
2025-09-01 19:48:15 +03:00
6fbca85d0c Merge branch 'development_decartive' of github.com:freeflowuniverse/herolib into development_decartive 2025-09-01 16:15:27 +02:00
8ee02d175e ... 2025-09-01 16:15:25 +02:00
Mahmoud-Emad
4746337b24 Merge branch 'development' into development_decartive 2025-09-01 13:11:03 +03:00
Mahmoud-Emad
46a3bcb840 refactor: Migrate from vweb to veb web framework
- Update all references from `vweb` to `veb`
- Add `veb.StaticHandler` to `Playground` struct
- Ensure error propagation for static file serving calls
- Apply consistent indentation across various module definitions
- Adjust documentation and comments for `veb` framework
2025-09-01 13:00:17 +03:00
Mahmoud-Emad
dde5f2f7e6 feat: Add robust cross-platform port availability check
- Introduce `port_check_available` function
- Use platform-specific tools (`lsof`, `ss`, `netstat`)
- Fallback to socket binding for port checks
- Integrate port check before running `ttyd`
- Simplify `tmux kill-session` error handling
2025-09-01 12:51:13 +03:00
Mahmoud-Emad
c7724f0779 Update the exe path 2025-09-01 12:05:21 +03:00
c702354260 Merge branch 'development' into development_decartive
* development:
  fix heromodels
2025-09-01 07:49:21 +02:00
Mahmoud-Emad
4afedc6541 chore: remove deprecated tmux example scripts and testing docs
- Delete `TESTING.md`
- Remove `tmux_cleanup.heroscript`
- Remove `tmux_setup.heroscript`
- Update `cleanup_test.heroscript` to delete session
2025-08-31 19:54:16 +03:00
Mahmoud-Emad
97760cfe87 feat: Implement comprehensive process cleanup for tmux
- Add `Pane.kill_processes` for main and child processes
- Include fallback process group cleanup for panes
- Implement window-level process cleanup
- Integrate session-level process cleanup
- Add tmux process cleanup test scripts
2025-08-31 19:26:45 +03:00
Mahmoud-Emad
b957394d2a Merge branch 'development_decartive' of https://github.com/freeflowuniverse/herolib into development_decartive 2025-08-31 17:56:14 +03:00
Mahmoud-Emad
7d28129f06 feat: implement dynamic pane resizing
- Add `resize_panes_equal()` to `Window`.
- Dynamically apply `tmux` layouts based on pane count.
- Implement `get_width()` and `get_height()` for `Pane`.
- Update test to create 4 panes and use equal resizing.
2025-08-31 17:56:03 +03:00
Timur Gordon
ab80ba8628 fix heromodels 2025-08-31 15:12:14 +02:00
cb43ec7f1a ... 2025-08-31 13:46:27 +02:00
9657e9aa97 Merge branch 'development' into development_decartive
* development: (53 commits)
  ...
  feat: Implement theming and modal UI improvements
  ...
  ...
  ...
  ...
  ...
  ...
  zinit client fixes
  git herocmd improvements
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
2025-08-31 13:22:58 +02:00
a25a12d4c9 ... 2025-08-31 13:22:52 +02:00
738bb16084 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-08-31 13:11:45 +02:00
f9717f8f5d ... 2025-08-31 13:11:43 +02:00
Mahmoud-Emad
4b0b5a26f8 feat: Add declarative tmux module functions
- Implement `tmux.session_ensure` for idempotent create
- Implement `tmux.window_ensure` with 1 to 16 pane layouts
- Implement `tmux.pane_ensure` to configure individual panes
- Add new declarative tmux example scripts
- Update docs for imperative and declarative paradigms
2025-08-31 11:59:23 +03:00
Mahmoud-Emad
0e8fdb0149 feat: Implement theming and modal UI improvements
- Introduce CSS custom properties for theming
- Add light theme support via `prefers-color-scheme`
- Enhance modal overlay, centering, and styling
- Improve modal responsiveness across breakpoints
- Remove prompt template and output copy buttons
2025-08-31 10:55:43 +03:00
2c7eaa4f5d ... 2025-08-30 12:37:18 +02:00
58aee3916c ... 2025-08-30 11:31:49 +02:00
79d2bb49f9 ... 2025-08-30 11:26:36 +02:00
6daffaeb94 ... 2025-08-29 12:51:19 +02:00
6edbfef12a ... 2025-08-29 10:44:46 +02:00
b7b89eece7 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-08-29 10:35:29 +02:00
90a3ce1181 ... 2025-08-29 10:35:27 +02:00
Timur Gordon
c813546085 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-08-29 10:18:25 +02:00
Timur Gordon
b0b1fbf2c2 zinit client fixes 2025-08-29 10:17:51 +02:00
Timur Gordon
3d86ec7cf5 git herocmd improvements 2025-08-29 10:17:34 +02:00
ce6cf3aa9c ... 2025-08-29 09:48:44 +02:00
03bb86bd72 ... 2025-08-29 09:48:13 +02:00
b146261432 ... 2025-08-29 09:47:54 +02:00
b29468c0c2 ... 2025-08-29 06:31:29 +02:00
8d1656c679 ... 2025-08-29 06:27:37 +02:00
0f6d6f731a ... 2025-08-29 06:13:50 +02:00
0f2d9f0aba ... 2025-08-28 21:28:03 +02:00
0221c0a28c ... 2025-08-28 21:21:57 +02:00
03961b291b ... 2025-08-28 20:42:59 +02:00
e89bd8ce24 ... 2025-08-28 19:22:14 +02:00
66d2ef2d97 ... 2025-08-28 19:18:56 +02:00
0a02ea353a ... 2025-08-28 18:46:24 +02:00
03c296ec2f ... 2025-08-28 18:39:18 +02:00
a96bebfd65 ... 2025-08-28 18:37:50 +02:00
fac9276479 ... 2025-08-28 18:27:32 +02:00
8440b18e2f ... 2025-08-28 17:37:57 +02:00
e340ad01ea ... 2025-08-28 17:19:32 +02:00
ae1f9d4477 .. 2025-08-28 16:12:34 +02:00
7b8ca007b7 ... 2025-08-28 16:10:59 +02:00
fb87adf87d ... 2025-08-28 16:02:28 +02:00
d52aa5dbd4 .l. 2025-08-28 14:40:09 +02:00
0bf586f748 Merge branch 'development_decartive' into development_builders
* development_decartive:
  refactor: use osal.processinfo_get for process stats
  feat: add declarative tmux and ttyd management

# Conflicts:
#	lib/osal/tmux/readme.md
2025-08-28 14:26:30 +02:00
a4472f095e Merge branch 'development' into development_builders
* development:
  minor example fixes
  feat: add comprehensive SSH agent management command
  refactor: Harden and improve SSH agent module
  ...
  feat: add editable ttyd dashboard mode
  feat: add CLI for dashboard management and 4-pane layout
  fix: Fix build
  ...
  refactor: update SSH agent examples and module structure
  feat: add tmux dashboard with ttyd integration
  refactor: Remove is_tmux_server_not_running_error function
  wip: pushing the code to sync in other branch
  refactor: Improve tmux API consistency and formatting

# Conflicts:
#	lib/osal/core/net.v
#	lib/virt/podman/factory.v
2025-08-28 14:26:06 +02:00
f5ca193fb4 ... 2025-08-28 14:25:07 +02:00
3f9844fd93 ... 2025-08-28 14:03:29 +02:00
76efe0438a ... 2025-08-28 13:29:17 +02:00
12c197207c ... 2025-08-28 13:28:05 +02:00
60fd795b1f ... 2025-08-28 12:02:48 +02:00
Mahmoud-Emad
ccfe02b1ee refactor: use osal.processinfo_get for process stats
- Replace `ps` command parsing with `osal.processinfo_get`
- Remove custom system memory detection and caching
- Update ProcessStats to use `osal` process info fields
- Ignore expected errors when stopping ttyd
- Add logging for ttyd stop operations
2025-08-28 12:55:12 +03:00
Mahmoud-Emad
b6324849a4 feat: add declarative tmux and ttyd management
- Implement `tmux.pane_split` action
- Add declarative `tmux.session_ttyd` and `tmux.window_ttyd`
- Include `tmux.session_ttyd_stop`, `window_ttyd_stop`, `ttyd_stop_all`
- Update tmux documentation and add usage examples
- Improve robustness of tmux session and window scanning
2025-08-28 12:45:46 +03:00
c10a7f2e7b ... 2025-08-28 09:17:10 +02:00
049f2316bd ... 2025-08-28 07:28:43 +02:00
4af635c4d1 Merge branch 'development_builders' of github.com:freeflowuniverse/herolib into development_builders 2025-08-28 05:39:53 +02:00
d1ec4ff568 lima installer 2025-08-28 05:39:51 +02:00
Mahmoud-Emad
13223dc03d chore: remove buildah example and run scripts
- Remove `buildah_example` script
- Remove `buildah_run_clean` script
- Remove `buildah_run_mdbook` script
- Remove `buildah_run` script
2025-08-27 13:11:57 +03:00
Mahmoud-Emad
9d79b6f2e2 feat: introduce consolidated Podman module with dual APIs
- Restructure Podman module into sub-files
- Introduce Simple API for quick Podman operations
- Add Podman machine management (init, start, list)
- Enhance Buildah integration with structured errors
- Define specific error types for Podman operations
- Update documentation and add comprehensive demo script
2025-08-27 13:10:53 +03:00
db9d2b5a0a ... 2025-08-27 10:20:52 +02:00
791988c420 ... 2025-08-27 09:57:06 +02:00
Timur Gordon
566d871399 minor example fixes 2025-08-27 09:41:33 +02:00
cbc6a9df2d .. 2025-08-27 09:36:11 +02:00
cace08d36c ... 2025-08-27 09:23:54 +02:00
a1fcdc1005 ... 2025-08-27 07:23:44 +02:00
c4d4dd5560 ... 2025-08-27 07:12:35 +02:00
Mahmoud-Emad
1228441fd6 feat: Add Buildah builder API and refactor module
- Introduce `Builder` struct for image creation
- Implement `PodmanFactory` methods for builder lifecycle
- Rename `herocontainers` module to `podman`
- Update `PodmanFactory.new` with platform checks
- Revise documentation for `podman` and Buildah usage
2025-08-26 20:28:38 +03:00
Mahmoud-Emad
ae5ab3133f Merge branch 'development_builders' of https://github.com/freeflowuniverse/herolib into development_builders 2025-08-26 14:24:34 +03:00
Mahmoud-Emad
b4c0d33b81 refactor: Update Podman install and uninstall methods
- Use native package managers for Linux and macOS
- Remove direct download and package file handling
- Add process termination during uninstallation
- Simplify temporary file cleanup in destroy
- Add checks for installed status in destroy
2025-08-26 14:24:18 +03:00
24ec468d37 ... 2025-08-26 11:36:53 +02:00
Omdanii
582184f51e Merge pull request #135 from freeflowuniverse/development_sshagent
Improve SSH agent module
2025-08-26 10:40:10 +03:00
f30d1fd503 ... 2025-08-26 04:53:39 +02:00
Mahmoud-Emad
e341f83f0f feat: add comprehensive SSH agent management command
- Introduce `hero sshagent` for full SSH agent management
- Implement `profile`, `push`, `auth`, `status` subcommands
- Enable smart key loading and shell profile integration
- Support remote key deployment and authorization verification
- Use `~/.ssh/hero-agent.sock` and ensure secure permissions
2025-08-25 17:22:13 +03:00
Mahmoud-Emad
ab6808c5f9 Merge branch 'development' into development_sshagent 2025-08-25 16:38:46 +03:00
Omdanii
289bfb3a98 Merge pull request #117 from freeflowuniverse/development_tmux
Improve tmux API consistency and formatting
2025-08-25 16:36:25 +03:00
Mahmoud-Emad
32e7a6df4f refactor: Harden and improve SSH agent module
- Add extensive security validations for SSH agent
- Implement robust `ssh-agent` auto-start script
- Enhance `sshagent` operations with improved error handling
- Revamp `sshagent` test suite for comprehensive coverage
- Update `sshagent` README with detailed documentation
2025-08-25 16:32:20 +03:00
50545ef5c1 ... 2025-08-25 12:53:25 +02:00
621faa73a5 Merge branch 'development_tmux' of github.com:freeflowuniverse/herolib into development_tmux 2025-08-25 12:04:43 +02:00
ffa5447e6f ... 2025-08-25 12:04:40 +02:00
Mahmoud-Emad
a62147d7cc feat: add editable ttyd dashboard mode
- Implement `-editable` CLI argument
- Configure ttyd for read/write access
- Introduce `TtydArgs` struct for ttyd parameters
- Update help message with ttyd modes
- Streamline Hero Web startup command
2025-08-25 11:52:13 +03:00
Mahmoud-Emad
dcb9714599 feat: add CLI for dashboard management and 4-pane layout
- Implement CLI for start, stop, status, restart
- Refactor dashboard setup into `start_dashboard` function
- Add `stop_dashboard` and `show_status` functions
- Expand tmux dashboard layout to 4 panes (2x2 grid)
- Integrate "Hero Web" service into dashboard panes
2025-08-25 10:16:10 +03:00
a99af1dfdd Merge branch 'development' into development_builders
* development:
  ...
  ...
  feat: add persistent AI chat interface
  feat: implement workspace search and improve UI
  feat: add ignore filtering to directory listing
  feat: add workspace management and file preview
  feat: Add workspace selection synchronization
  feat: Add directory listing functionality
  feat: redesign UI for improved file explorer and workspaces
  docs: add HeroLib Web UI documentation
  feat: improve Heroprompt UI and refactor modules
  feat: add modular web UI features
  bump version to 1.0.29
2025-08-25 09:07:47 +02:00
bf999d8fcb ... 2025-08-25 09:07:00 +02:00
Mahmoud-Emad
750e34cbe4 fix: Fix build 2025-08-25 09:43:37 +03:00
Mahmoud-Emad
25f4e4f03e Merge branch 'development' into development_tmux 2025-08-25 09:40:18 +03:00
Omdanii
0bc6150986 Merge pull request #118 from freeflowuniverse/development_heroprompt
Development heroprompt
2025-08-25 09:39:47 +03:00
4c1ed80b85 ... 2025-08-25 07:16:16 +02:00
85eaee4c0a ... 2025-08-25 07:14:11 +02:00
161f6786bd Merge branch 'development' into development_tmux
* development:
  ...

# Conflicts:
#	lib/osal/sshagent/agent.v
#	lib/osal/sshagent/play.v
2025-08-25 07:00:06 +02:00
692838566a Merge branch 'development' into development_heroprompt
* development:
  ...
2025-08-25 06:59:37 +02:00
856a5add22 ... 2025-08-25 06:59:30 +02:00
5f75c542df ... 2025-08-25 06:34:39 +02:00
43e7c087db Merge branch 'development' into development_tmux
* development:
  ...
  ...
  ...
  ...

# Conflicts:
#	examples/osal/sshagent.vsh
#	examples/osal/sshagent/sshagent_example.v
#	examples/osal/tmux.vsh
#	lib/osal/sshagent/agent.v
#	lib/osal/sshagent/builder_integration.v
#	lib/osal/tmux/tmux_pane.v
#	lib/osal/tmux/tmux_scan.v
#	lib/osal/tmux/tmux_session.v
#	lib/osal/tmux/tmux_window.v
2025-08-25 06:34:03 +02:00
e0a81f9525 Merge branch 'development' into development_heroprompt
* development:
  ...
  ...

# Conflicts:
#	lib/threefold/grid4/datamodel/model_node.v
2025-08-25 06:33:07 +02:00
80741a3500 ... 2025-08-25 06:31:32 +02:00
c6d703b860 ... 2025-08-25 06:29:42 +02:00
836c87fbec ... 2025-08-25 06:28:42 +02:00
5f683ec4a8 ... 2025-08-25 06:09:51 +02:00
77d9b5c869 Merge branch 'development' into development_heroprompt
* development:
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...

# Conflicts:
#	lib/threefold/grid4/datamodel/model_slice_compute.v
#	lib/threefold/grid4/datamodel/model_slice_storage.v
2025-08-25 06:01:35 +02:00
607b2b0881 ... 2025-08-25 05:58:44 +02:00
01163ef534 ... 2025-08-25 05:44:45 +02:00
Mahmoud-Emad
a37dbd2438 refactor: update SSH agent examples and module structure
- Refactor `gittools` to remove `sshagent` import
- Update `sshagent.loaded()` to use `ssh-add -l` command
- Relocate and expose `remote_copy` and `remote_auth` functions
- Improve SSH agent examples and remove Linux tests
- Optimize `sshagent` module and `play` function imports
2025-08-24 23:54:57 +03:00
Mahmoud-Emad
9945cfb52c Merge branch 'development' into development_tmux 2025-08-24 23:15:34 +03:00
Mahmoud-Emad
25327053b9 feat: add tmux dashboard with ttyd integration
- Create script for 3-pane tmux dashboard
- Run Python HTTP server, counter, and htop in panes
- Add `run_ttyd` function to `Session` struct
- Add `run_ttyd` function to `Window` struct
- Expose tmux session and window via ttyd
2025-08-24 23:12:32 +03:00
Mahmoud-Emad
426a53a50d refactor: Remove is_tmux_server_not_running_error function 2025-08-24 18:10:30 +03:00
Mahmoud-Emad
b26893bf45 wip: pushing the code to sync in other branch 2025-08-24 17:58:09 +03:00
4e20df3eb8 ... 2025-08-24 16:42:07 +02:00
a2a9b07238 ... 2025-08-24 16:40:07 +02:00
8532373e7e ... 2025-08-24 16:19:41 +02:00
c7b2ea9e2a ... 2025-08-24 16:00:13 +02:00
698724f810 ... 2025-08-24 15:43:07 +02:00
4f54551f14 ... 2025-08-24 15:42:01 +02:00
Mahmoud-Emad
117c9ac67c refactor: Improve tmux API consistency and formatting
- Refactor `logs_get_new` to use `LogsGetArgs` struct
- Return window as reference from `window_new`
- Standardize indentation and spacing
- Remove excessive blank lines
- Comment out initial example usage
2025-08-24 16:31:04 +03:00
e47d311c99 ... 2025-08-24 15:28:57 +02:00
6de2153f11 ... 2025-08-24 15:24:52 +02:00
Mahmoud-Emad
0e7344ae4a feat: add persistent AI chat interface
- Implement persistent AI chat with conversation history.
- Add chat sidebar for conversation management (create, load, delete).
- Enhance message display with markdown, copy, regenerate actions.
- Integrate interactive chat input (auto-resize, char count, typing indicator).
- Apply comprehensive responsive and accessibility styles to chat UI.
2025-08-24 16:13:25 +03:00
810cbda176 ... 2025-08-24 15:10:03 +02:00
d07aec8434 ... 2025-08-24 15:02:22 +02:00
4ab65ac61b ... 2025-08-24 14:56:20 +02:00
1dd8c29735 ... 2025-08-24 14:47:48 +02:00
e7a36f47e8 ... 2025-08-24 14:41:12 +02:00
Mahmoud-Emad
7fe03b5a5d feat: implement workspace search and improve UI
- Add workspace search API endpoint
- Integrate workspace search into frontend UI
- Implement synchronized scrolling for code previews
- Standardize API error/success JSON responses
- Improve file tree loading animations & interaction
2025-08-24 15:14:25 +03:00
9f39481cb4 ... 2025-08-24 14:02:41 +02:00
2253ef71e6 ... 2025-08-24 13:56:54 +02:00
Mahmoud-Emad
cd512813e3 feat: add ignore filtering to directory listing
- Add `list_directory_filtered` function with ignore logic
- Update `default_gitignore` with common VCS and build patterns
- Integrate ignore filtering into `Workspace.list_dir`
- Rename project to HeroPrompt in README
- Update README features and usage descriptions
2025-08-24 13:57:25 +03:00
Mahmoud-Emad
d6ea18e6db feat: add workspace management and file preview
- Add workspace update and delete API endpoints
- Redesign selected files display to use interactive cards
- Implement VS Code-style modal for file content preview
- Enhance file tree with animations and local state
- Update UI styles for explorer, forms, and modals
2025-08-24 13:40:51 +03:00
Mahmoud-Emad
cc93081b15 feat: Add workspace selection synchronization
- Create `codewalker` module with file system utilities
- Refactor `Workspace` file operations to use `codewalker`
- Add `include_tree` flag to `HeropromptChild` struct
- Implement new `/selection` API endpoint for workspace
- Sync frontend selection state to backend via new API
2025-08-24 12:58:09 +03:00
Mahmoud-Emad
6098f166bb feat: Add directory listing functionality
- Add `list_dir` function to `Workspace` struct
- Implement path handling and directory scanning logic
- Refine struct formatting for `Node`, `ComputeSlice`, `StorageSlice`
- Update `StorageSlice.pricing_policy` comment
- Adjust whitespace in CSS styles
2025-08-24 12:00:12 +03:00
Mahmoud-Emad
3050433cfd Merge branch 'development' into development_heroprompt 2025-08-24 11:35:08 +03:00
Mahmoud-Emad
de9e310867 feat: redesign UI for improved file explorer and workspaces
- Refactor file tree logic into `SimpleFileTree` class
- Implement new explorer with collapse, refresh, search, and selection controls
- Redesign selection, prompt, and chat workspaces with new layouts and styles
- Introduce dedicated CSS icon set for various UI elements
- Add prompt generation and clipboard copy functionality for prompt output
2025-08-24 11:34:30 +03:00
9398d653d3 ... 2025-08-23 14:06:15 +02:00
66240aa9f2 ... 2025-08-22 14:33:01 +02:00
Mahmoud-Emad
03de3a6aee docs: add HeroLib Web UI documentation
- Add quick start guide with code example
- List key features of the UI
- Detail built-in tools and their paths
2025-08-21 20:04:25 +03:00
Mahmoud-Emad
cf187d46b3 feat: improve Heroprompt UI and refactor modules
- Refactor all UI rendering logic into a single `ui` module
- Centralize static assets serving to `/static` directory
- Redesign Heroprompt page with Bootstrap 5 components
- Enhance workspace management and file tree interactions
- Add Bootstrap modal support for UI dialogs
2025-08-21 20:01:43 +03:00
Mahmoud-Emad
066f339b78 Merge branch 'development_heroprompt' of https://github.com/freeflowuniverse/herolib into development_heroprompt 2025-08-21 18:28:49 +03:00
Mahmoud-Emad
68dd957421 feat: add modular web UI features
- Enable `web` command to start UI server
- Centralize web server setup and static serving
- Implement modular UI for chat and script editor
- Refactor Heroprompt UI into its own module
- Introduce dynamic theme switching and mobile menu
2025-08-21 18:28:17 +03:00
b168d647da ... 2025-08-21 17:18:41 +02:00
3f46a35f7b ... 2025-08-21 12:45:03 +02:00
e6021c0bde ... 2025-08-21 12:44:42 +02:00
9af7a62381 ... 2025-08-21 12:43:03 +02:00
245d45bb6b ... 2025-08-21 12:37:35 +02:00
238c35d45b ... 2025-08-21 12:36:54 +02:00
df3817120f ... 2025-08-21 12:35:06 +02:00
2a38221d7f bump version to 1.0.29 2025-08-21 12:27:48 +02:00
40b3911781 ... 2025-08-21 12:21:52 +02:00
febe87c55e ... 2025-08-21 12:17:40 +02:00
e8d6193d06 Merge branch 'development' into development_heroprompt
* development:
  ...
2025-08-21 12:16:42 +02:00
1d98724c02 ... 2025-08-21 12:16:32 +02:00
26731c38b5 ... 2025-08-21 12:13:36 +02:00
a484da769c Merge branch 'development_heroprompt' of github.com:freeflowuniverse/herolib into development_heroprompt 2025-08-21 12:11:11 +02:00
cbccce3413 ... 2025-08-21 12:11:09 +02:00
Mahmoud-Emad
27c8c06cdb chore: Comment the web ui package 2025-08-21 13:10:44 +03:00
Mahmoud-Emad
35eee2dcad Merge branch 'development_heroprompt' of https://github.com/freeflowuniverse/herolib into development_heroprompt 2025-08-21 13:07:09 +03:00
cba4a6d7c1 ... 2025-08-21 12:06:21 +02:00
1217d7b10d ... 2025-08-21 12:06:03 +02:00
Mahmoud-Emad
cfd5711c86 chore: comment out web command functionality 2025-08-21 13:06:01 +03:00
9642922445 ... 2025-08-21 12:05:20 +02:00
9b2b7283c0 ... 2025-08-21 12:02:28 +02:00
9658f1af8d ... 2025-08-21 12:01:36 +02:00
13bed3d48a ... 2025-08-21 11:59:06 +02:00
e620dfc6e3 Merge branch 'development' of github.com:freeflowuniverse/herolib into development
* 'development' of github.com:freeflowuniverse/herolib:
  remove const from default field value
2025-08-21 11:38:07 +02:00
1171b7b6d6 Merge branch 'development_heroprompt' of github.com:freeflowuniverse/herolib into development_heroprompt 2025-08-21 11:37:19 +02:00
3029bf661a ... 2025-08-21 11:37:17 +02:00
Timur Gordon
26c945ed08 remove const from default field value 2025-08-21 11:37:11 +02:00
1b90ce41e6 ... 2025-08-21 11:15:08 +02:00
e0a8bc32e7 .. 2025-08-21 11:10:13 +02:00
Mahmoud-Emad
f5d9c6019b Merge branch 'development' into development_heroprompt 2025-08-21 11:06:57 +03:00
Mahmoud-Emad
27f48de1f1 feat: Add directory and file selection
- Add button to select directories
- Implement `addDirToSelection` API call
- Refactor file selection to `addFileToSelection`
- Update file selection button title
- Remove commented preview logic from file links
2025-08-21 10:59:20 +03:00
add4fb5c48 ... 2025-08-21 09:55:30 +02:00
17cdfd8a0d ... 2025-08-21 09:49:25 +02:00
Mahmoud-Emad
854eb9972b feat: integrate Heroprompt UI and backend
- Replace generic UI with dedicated Heroprompt web interface
- Implement new Heroprompt-specific backend APIs
- Develop client-side logic for file browsing and selection
- Enhance workspace configuration and management capabilities
- Remove deprecated generic UI modules and code
2025-08-21 10:49:02 +03:00
c0339a0922 ... 2025-08-21 09:48:50 +02:00
601e5db76a , 2025-08-21 09:45:41 +02:00
b109299210 ... 2025-08-21 09:38:20 +02:00
082dbed910 ... 2025-08-21 09:07:29 +02:00
6e32a01faa ... 2025-08-21 08:38:40 +02:00
d73fe6eb25 ... 2025-08-20 18:57:32 +02:00
4a0fd8edde ... 2025-08-20 18:44:42 +02:00
34202de296 ... 2025-08-20 18:39:52 +02:00
3988548fe9 ... 2025-08-19 05:57:31 +02:00
3bcb6bee80 ... 2025-08-19 05:51:43 +02:00
7e33acb425 ... 2025-08-18 17:17:10 +02:00
75d20fd8e1 ... 2025-08-18 17:16:03 +02:00
Mahmoud-Emad
c38fdd86ac Merge branch 'development' into development_heroprompt 2025-08-18 13:38:13 +03:00
Mahmoud-Emad
9069816db1 feat: implement full heroprompt workspace management
- Add create, save, get, list, and delete for workspaces
- Enable adding and removing files/dirs by path or name
- Integrate codewalker for recursive file discovery
- Make workspaces stateful with created/updated timestamps
- Update example to demonstrate new lifecycle methods
2025-08-18 09:51:16 +03:00
1903ebe045 ... 2025-08-18 07:30:00 +02:00
3dee0d7eef Merge branch 'development_codewalker' of github.com:freeflowuniverse/herolib into development_codewalker 2025-08-18 07:23:29 +02:00
ba85e91c58 .. 2025-08-18 07:23:27 +02:00
Mahmoud-Emad
1ed08b3ca4 fix: add the removed README 2025-08-17 20:19:41 +03:00
Mahmoud-Emad
bcee46fa15 refactor: overhaul codewalker with improved parser and ignore logic
- Implement level-scoped .gitignore/.heroignore matching
- Rewrite directory walker to use new ignore matcher
- Replace filemap parser with robust header-based logic
- Support `FILE`, `FILECHANGE`, and legacy header formats
- Add extensive tests for new parsing and ignore features
2025-08-17 15:23:15 +03:00
f3449d6812 ... 2025-08-17 11:07:26 +02:00
Mahmoud-Emad
3c5e0a053e Merge branch 'development' into development_heroprompt 2025-08-17 11:42:16 +03:00
Mahmoud-Emad
f6c077c6b5 refactor: simplify heroprompt workspace selection model
- Introduce HeropromptChild to unify file and dir items
- Replace nested Dir/File structs with a flat `children` list
- Generate prompt content by traversing the filesystem on-demand
- Add `workspace.add_file` for direct file selection
- Simplify `workspace.add_dir` to only add the directory path
2025-08-17 11:41:29 +03:00
df5d91e7b6 ... 2025-08-17 10:41:09 +02:00
25e01e308c ... 2025-08-17 10:13:45 +02:00
7204aff27e ... 2025-08-17 10:04:58 +02:00
cd91734a84 ... 2025-08-16 19:51:06 +02:00
6306883463 ... 2025-08-16 19:42:08 +02:00
42bfecffb6 ... 2025-08-16 19:37:42 +02:00
f7d5415484 ... 2025-08-16 19:27:31 +02:00
5825640c2c ... 2025-08-16 17:45:04 +02:00
de60c5f78e ... 2025-08-16 11:23:58 +02:00
be19609855 ... 2025-08-16 10:07:35 +02:00
27bc172257 ... 2025-08-16 07:31:32 +02:00
6732928156 ... 2025-08-16 05:21:52 +02:00
3bd1117210 ... 2025-08-16 05:20:51 +02:00
1cd8e8c299 ... 2025-08-16 05:13:18 +02:00
97d506ecbf ... 2025-08-15 17:57:16 +02:00
43ffedfad8 ... 2025-08-15 08:52:46 +02:00
71298a9704 ... 2025-08-15 08:25:00 +02:00
e76f558f97 ... 2025-08-15 07:41:10 +02:00
e030309b7f ... 2025-08-15 07:09:40 +02:00
e77f923cd2 ... 2025-08-15 06:30:12 +02:00
bd86f2c4f7 ... 2025-08-15 06:20:00 +02:00
Mahmoud-Emad
2d00d6cf9f feat: implement workspace file tree listing
- Add `list()` method to generate a full workspace file tree
- Introduce `WorkspaceItem` and `WorkspaceList` structs
- Remove `HeropromptSession` to simplify the public API
- Rename Heroscript action to `heropromptworkspace.configure`
- Enable full heroscript encoding/decoding for workspaces
2025-08-14 15:45:26 +03:00
Mahmoud-Emad
a58d72615d feat: Add recursive directory selection and enhance prompt builder
- Add `select_all` option to recursively add directory contents
- Implement `select_all_files_and_dirs` for file traversal
- Rework prompt building with file tree and content formatters
- Improve `get_file_extension` to handle dotfiles and special files
- Update prompt template to use new structured data model
2025-08-14 10:56:05 +03:00
Mahmoud-Emad
14771ed944 feat: add heroprompt module for prompt generation
- Introduce sessions and workspaces for managing context
- Allow adding directories and selecting files
- Generate structured prompts with file maps and content
- Add example script and a prompt template
- Define core data models like `HeropromptWorkspace`
2025-08-13 20:13:01 +03:00
Mahmoud-Emad
a6d4a23172 feat: add Heroprompt workspace management UI
- Add HTML, CSS, and JS for the Heroprompt feature
- Implement a three-panel UI for workspaces and files
- Add logic for creating/deleting workspaces in localStorage
- Enable adding directories and selecting files for
2025-08-13 15:37:36 +03:00
Mahmoud-Emad
5c77c6bd8d fix: Rename reporomt to heroprompt 2025-08-13 14:17:29 +03:00
b0ff9e3fbf ... 2025-08-13 13:12:55 +02:00
Mahmoud-Emad
3f82240564 feat: add web command to run Hero UI
- Add `web` command to start the Hero UI server
- Introduce `--host`, `--port`, and `--open` flags
- Implement cross-platform browser opening
- Update UI factory arguments for server configuration
2025-08-13 14:08:00 +03:00
06a89aead9 Merge branch 'development' of github.com:freeflowuniverse/herolib into development
# Conflicts:
#	lib/develop/gittools/gittools_do.v
2025-08-13 12:10:21 +02:00
23a723e17f ... 2025-08-13 12:09:14 +02:00
1501a09e62 ... 2025-08-13 12:09:11 +02:00
Omdanii
1f9b8c1e76 Merge pull request #112 from freeflowuniverse/development_fix_git_clone
Prevent double clone for clone command with URL
2025-08-13 13:08:31 +03:00
Mahmoud-Emad
f7ed2ea31e fix: prevent double clone for clone command with URL
- Differentiate logic when a URL is used for the clone command.
- Parse URL to get identifiers without cloning the repository.
- This avoids an implicit clone before the explicit one.
- Retain original `get_repo` behavior for other commands.
2025-08-13 13:07:30 +03:00
15aeb136b2 ... 2025-08-13 10:12:57 +02:00
50f33e9303 ... 2025-08-13 10:03:33 +02:00
f026565f77 ... 2025-08-13 10:01:09 +02:00
0845feffac ... 2025-08-13 09:48:56 +02:00
55f0621983 ... 2025-08-13 09:35:58 +02:00
75363d7aeb ... 2025-08-13 08:55:38 +02:00
1f9bc11a2e ... 2025-08-13 08:49:44 +02:00
aab018925d ... 2025-08-13 07:23:14 +02:00
5fa361256a ... 2025-08-13 07:18:02 +02:00
42fe7b0a0d Merge branch 'development_fix_docusaurus' of github.com:freeflowuniverse/herolib into development_fix_docusaurus
* 'development_fix_docusaurus' of github.com:freeflowuniverse/herolib:
  refactor: Improve docusaurus import and site handling
2025-08-13 05:59:46 +02:00
011e5b039e ... 2025-08-13 05:59:40 +02:00
Mahmoud-Emad
e9bcf6ef69 refactor: Improve docusaurus import and site handling
- Simplify command logic to use a single defined site
- Enhance git import to resolve paths relative to project root
- Add `docusaurus.export` action to trigger `build_publish`
- Change asset import destination from `docs` to `static`
- Add `dsite_get_only` helper for simplified site access
2025-08-13 04:19:32 +03:00
f885563982 Co-authored-by: Omdanii <mahmmoud.hassanein@gmail.com> 2025-08-12 16:01:27 +02:00
ffff44f347 .. 2025-08-12 15:52:13 +02:00
Mahmoud-Emad
0e1450b5db chore: add debug prints and perform code cleanup
- Add extensive debug prints for troubleshooting
- Comment out docusaurus build/dev action logic
- Rename gittools parameters for clarity (reset/pull)
- Apply consistent formatting to function calls
- Remove unused imports in playbook include module
2025-08-12 13:37:01 +03:00
f8734a7e9f .. 2025-08-12 11:07:09 +02:00
c05ec6be7f ... 2025-08-12 11:03:49 +02:00
8677d177cb ... 2025-08-12 11:02:21 +02:00
dd37eeaa29 ... 2025-08-12 10:58:53 +02:00
d5753ee794 replace 2025-08-12 10:39:18 +02:00
6b46b3dbaa ... 2025-08-12 10:36:26 +02:00
4cd5b51085 ... 2025-08-12 10:33:29 +02:00
0a7851b920 ... 2025-08-12 09:41:50 +02:00
a0fdaf395e ... 2025-08-12 09:33:53 +02:00
2c5a2ace17 ... 2025-08-11 22:34:23 +02:00
965a2bebb7 ... 2025-08-11 22:12:44 +02:00
2c08ee8687 to compare 2025-08-11 21:41:38 +02:00
e105dd73b5 Merge branch 'development_fix_docusaurus_include' into development
* development_fix_docusaurus_include:
  refactor: Rework playbook include and site import logic
2025-08-11 21:26:49 +02:00
f5dfe8c0af Merge branch 'fix-issue-104' into development
* fix-issue-104:
  Fix issue #104: Fix all biztools examples to use playbook.new()
  Fix issue #104: Add fixed examples and solution documentation
  Fix issue #104: Add notworking.md documenting biztools examples test results

# Conflicts:
#	examples/biztools/notworking.md
2025-08-11 21:26:18 +02:00
ac97e9e7bc Merge branch 'copilot/fix-104' into development
* copilot/fix-104:
  Complete testing of all biztools examples - all 11 scripts are non-functional
  Initial plan
2025-08-11 21:25:57 +02:00
Mahmoud-Emad
beae2cef82 refactor: Rework playbook include and site import logic
- Replace manual script concatenation with playbook include handling
- Preserve site configuration (imports, menu) during generation
- Add support for copying static files from imported content
- Handle static assets from sibling `ebooksall` directories
- Fix import copy logic to not delete destination before copying
2025-08-11 21:53:24 +03:00
2b23771056 ... 2025-08-11 16:38:54 +02:00
19632b4b4b ... 2025-08-11 15:32:12 +02:00
31c033300a Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-08-11 11:51:54 +02:00
ca4127319d ... 2025-08-11 11:51:51 +02:00
openhands
d3d8f0d0f1 ... 2025-08-10 03:50:00 +00:00
openhands
2968e4dddc Fix issue #104: Fix all biztools examples to use playbook.new() 2025-08-09 20:08:51 +00:00
copilot-swe-agent[bot]
30c7951058 Complete testing of all biztools examples - all 11 scripts are non-functional
Co-authored-by: despiegk <6021844+despiegk@users.noreply.github.com>
2025-08-09 20:01:58 +00:00
openhands
af63e266d8 Fix issue #104: Add fixed examples and solution documentation 2025-08-09 20:01:37 +00:00
openhands
5d1e3d416e Fix issue #104: Add notworking.md documenting biztools examples test results 2025-08-09 19:57:37 +00:00
copilot-swe-agent[bot]
dd9dc59485 Initial plan 2025-08-09 19:51:51 +00:00
b473630ceb ... 2025-08-09 06:16:49 +02:00
a34b8b70ba ... 2025-08-08 21:36:46 +02:00
fd195f0824 ... 2025-08-08 17:51:57 +02:00
a727d19281 ... 2025-08-08 17:13:33 +02:00
52c88bccb5 bump version to 1.0.28 2025-08-08 17:02:05 +02:00
85cb868bff ... 2025-08-08 17:01:27 +02:00
4339220b42 bump version to 1.0.28 2025-08-08 17:01:11 +02:00
2eb62063f2 bump version to 1.0.27 2025-08-08 16:42:25 +02:00
eaccbe610f ... 2025-08-08 16:28:05 +02:00
53e685241a ... 2025-08-08 16:17:52 +02:00
9d87fc62f3 ... 2025-08-08 16:00:37 +02:00
682abdbda9 ... 2025-08-08 15:53:25 +02:00
6308d232aa ... 2025-08-08 15:46:01 +02:00
56d6a05ced ... 2025-08-08 13:19:30 +02:00
0c93a5abe8 ... 2025-08-08 13:15:31 +02:00
2726ecbe2e ... 2025-08-08 13:11:05 +02:00
aa26ae60e2 ... 2025-08-08 09:25:56 +02:00
Mahmoud-Emad
edefab866f docs: add hero command usage and update examples
- Add recommended `hero` command workflow section
- Update `!!docusaurus.add` example with `play` parameter
- Clarify comments for optional git parameters
2025-08-07 16:29:30 +03:00
Mahmoud-Emad
b01e6a5a4c refactor: Centralize Docusaurus site processing logic
- Add central `process_site_from_path` function
- Recursively process heroscript files in `cfg` directory
- Remove duplicated site processing from `run` and `add` commands
- Respect `play` parameter from heroscript `define` block
2025-08-07 16:22:35 +03:00
Mahmoud-Emad
843b20804b refactor: improve docusaurus site creation and handling
- Change site.new to always create/overwrite a site
- Add early exit to site.play if no config exists
- Use explicit sitename from docusaurus.config
- Enable openai.play action processing
- Remove debug code and improve struct initialization
2025-08-07 13:42:53 +03:00
daf6ce5126 Merge branch 'development_fix_hero_and_ci' of github.com:freeflowuniverse/herolib into development_fix_hero_and_ci
* 'development_fix_hero_and_ci' of github.com:freeflowuniverse/herolib:
  refactor: overhaul Docusaurus command and generation
2025-08-07 10:23:12 +02:00
52214f79d6 ... 2025-08-07 10:23:06 +02:00
Mahmoud-Emad
6ae6cc35ee Merge branch 'development_fix_hero_and_ci' of https://github.com/freeflowuniverse/herolib into development_fix_hero_and_ci 2025-08-07 10:54:42 +03:00
Mahmoud-Emad
82a46e8149 refactor: overhaul Docusaurus command and generation
- Rework `hero docusaurus` command to use local `cfg` files
- Scan and export doctree collections during site generation
- Fix `baseUrl` redirect path handling in `index.tsx`
- Add cycle detection for `play.include` in playbooks
- Improve site config processing to prevent duplicate items
2025-08-07 10:46:57 +03:00
93953ed570 ... 2025-08-07 08:15:04 +02:00
2667856633 ... 2025-08-06 13:00:51 +02:00
3bca5f661e ... 2025-08-06 12:50:30 +02:00
d4df226381 ... 2025-08-06 12:36:09 +02:00
d56a04e3ea Merge branch 'development' into development_fix_hero_and_ci
* development:
  ...

# Conflicts:
#	lib/core/herocmds/docusaurus.v
#	lib/data/encoderhero/decoder.v
#	lib/data/encoderhero/postgres_client_decoder_test.v
#	lib/web/site/play.v
2025-08-06 08:55:07 +02:00
e4c204376e Merge branch 'development' of github.com:freeflowuniverse/herolib into development
# Conflicts:
#	lib/core/herocmds/docusaurus.v
#	lib/web/docusaurus/factory.v
2025-08-06 08:51:38 +02:00
04403b62a4 ... 2025-08-06 08:50:32 +02:00
Mahmoud-Emad
3b0232ebe3 refactor: improve skip attribute detection logic
- Normalize attributes by removing all whitespace
- Simplify conditional logic for skip attribute check
- Add fallback skip check for fields named 'other'
- Remove debugging print statements
2025-08-05 20:14:47 +03:00
Mahmoud-Emad
29e0efa3d6 debug: Add some print statments to see the output in the CI 2025-08-05 20:05:30 +03:00
Mahmoud-Emad
c81af5e235 fix: make skip attribute detection more robust
- Replace simple `contains('skip')` with stricter checks
- Normalize attribute string before checking
- Avoid matching 'skip' as a substring of another word
- Handle space and semicolon-separated attribute lists
2025-08-05 19:52:01 +03:00
Mahmoud-Emad
b15c4cd15a refactor: Change hero action syntax to verb.noun
- Change action name format from `obj.verb` to `verb.obj`
- Update decoder to look for `define.obj` or `configure.obj`
- Modify encoder export to use the new `define.obj` prefix
- Update all test constants and scripts to the new syntax
- Make Remark struct public for test visibility
2025-08-05 19:02:26 +03:00
Mahmoud-Emad
65d75a8148 test: add link_def_test.v 2025-08-05 18:07:26 +03:00
Mahmoud-Emad
b04e1d7f99 fix: Return the test_basic.vsh file back 2025-08-05 17:58:45 +03:00
Mahmoud-Emad
a848eaa18b refactor: Improve playbook processing and add generation
- Trigger doc content generation after playbook processing
- Remove mutable variables for playbook actions
- Eliminate `action.done = true` assignments
- Derive site name from title if not explicitly provided
- Separate local path and git URL for docusaurus sites
2025-08-05 17:47:33 +03:00
Mahmoud-Emad
ccf2d4a3a5 fix: Fix docusaurus compilation issues in development branch
- Update docusaurus.v to use correct API (dsite_add instead of add)
- Fix factory.v compiler bug by rewriting problematic or block syntax
- Ensure compilation works with current docusaurus module structure
2025-08-05 15:34:46 +03:00
Mahmoud-Emad
59acea177d test: overhaul mycelium two-node communication test
- Start two local mycelium nodes without TUN interfaces
- Add pre-test cleanup for processes and configurations
- Implement readiness check to wait for servers to start
- Test bidirectional messaging between the two nodes
- Verify message payload and source public key
2025-08-05 15:11:46 +03:00
5cb52ba6b1 ... 2025-08-04 09:35:50 +02:00
6a2ea52e48 ... 2025-08-04 08:55:12 +02:00
c853f3b0ce ... 2025-08-04 08:01:26 +02:00
07bd258e54 ... 2025-08-04 07:05:04 +02:00
52f7a7a2b8 Merge branch 'development_ds' into development_fix_herobin
* development_ds:
  refactor: improve config path handling and clean up code
  refactor: dynamically load site config from heroscript
  feat: add multi-site support and playbook enhancements

# Conflicts:
#	lib/web/docusaurus/dsite_configuration.v
2025-08-04 05:41:59 +02:00
cf4d9e86c8 Merge branch 'development_ds' of github.com:freeflowuniverse/herolib into development_ds
* 'development_ds' of github.com:freeflowuniverse/herolib:
  refactor: improve config path handling and clean up code
  refactor: dynamically load site config from heroscript
  feat: add multi-site support and playbook enhancements
2025-08-04 05:41:11 +02:00
Mahmoud-Emad
44effe9a4b refactor: improve config path handling and clean up code
- Allow specifying project root or cfg dir for config
- Remove verbose debug print statements during load
- Remove unused site.page action find operation
- Improve validation for relative paths in remove list
2025-08-03 18:07:53 +03:00
Mahmoud-Emad
2502f0a655 refactor: dynamically load site config from heroscript
- Process heroscript files using a playbook
- Dynamically add config, menus, and page files
- Retrieve site config from the processed playbook
- Override site description from meta config
- Remove unused 'deploykey' flag and import
2025-08-03 17:33:23 +03:00
Mahmoud-Emad
d747977185 feat: add multi-site support and playbook enhancements
- Refactor `site` module to process multiple configurations
- Add environment variable templating for playbook actions
- Activate playbook actions for setting coderoot and params
- Improve docusaurus config with metadata fallbacks
- Fix docusaurus navbar generation when logo is not defined
2025-08-03 12:14:55 +03:00
4b900e383a Merge branch 'development_ds' into development_fix_herobin
* development_ds:
  ...
  refactor: improve session action handling in play_core
  refactor: adapt docusaurus to use generic site module
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...
  ...

# Conflicts:
#	lib/biz/bizmodel/play.v
#	lib/threefold/grid4/cloudslices/play.v
#	lib/threefold/grid4/farmingsimulator/play.v
#	lib/web/docusaurus/dsite.v
#	lib/web/docusaurus/dsite_add.v
#	lib/web/docusaurus/dsite_configuration.v
#	lib/web/docusaurus/dsite_generate.v
2025-08-03 04:47:53 +02:00
8ae0d6e401 ... 2025-08-03 04:44:55 +02:00
Mahmoud-Emad
198a394be8 refactor: improve session action handling in play_core
- Clean up `play_core` by removing dead code and unused imports
- Check `action.name` directly instead of param existence
- Allow 'value' as an alias for 'val' in session env actions
- Use `env_set` for `env_set_once` to avoid duplicate errors
2025-07-31 17:59:44 +03:00
Mahmoud-Emad
697c500e35 refactor: adapt docusaurus to use generic site module
- Introduce a new generic `site` module for web generation
- Update `herocmds` to use the new site creation flow
- Simplify docusaurus playbook logic with a `docusaurus.play` fn
- Refactor site generation to act on `Site` struct directly
- Fix playbook find filter to use wildcard `*`
2025-07-31 14:42:36 +03:00
Mahmoud-Emad
e6c1d84836 refactor: Generalize playbook find method and restructure site module
- Replace `actions_find` with a more generic `find(filter:)`
- Rename `siteconfig` module and related types to `site`
- Introduce a `Site` object to encapsulate configuration
- Update site generation to accept a playbook object directly
- Remove redundant blank lines and format code
2025-07-31 14:02:46 +03:00
e837912363 ... 2025-07-31 03:51:36 +02:00
50a76dd096 ... 2025-07-31 03:44:44 +02:00
a7f6548bea ... 2025-07-30 23:43:41 +02:00
34da4f06e1 ... 2025-07-30 23:00:49 +02:00
932b6508c9 ... 2025-07-30 22:23:24 +02:00
bfaa2446cd ... 2025-07-30 22:12:19 +02:00
bfe3110894 ... 2025-07-30 21:36:30 +02:00
59386bb1c2 ... 2025-07-30 20:06:27 +02:00
b99f5ae6e9 ... 2025-07-30 19:17:14 +02:00
4472dc7d04 ... 2025-07-30 19:14:31 +02:00
d3d7eccf3d ... 2025-07-30 19:08:15 +02:00
7e250d1224 ... 2025-07-30 18:58:11 +02:00
14d8d5af8d ... 2025-07-30 18:51:29 +02:00
1cb6c486df ... 2025-07-30 17:43:39 +02:00
bc163eb61d ... 2025-07-30 17:35:19 +02:00
802f6e074d ... 2025-07-30 15:58:04 +02:00
4bf4294c42 ... 2025-07-30 15:28:14 +02:00
cb13febd78 ... 2025-07-30 15:24:10 +02:00
685a58aa14 ... 2025-07-30 15:21:10 +02:00
2bc2c07114 ... 2025-07-30 15:08:23 +02:00
66757c52d7 ... 2025-07-30 15:00:20 +02:00
9fd551e0f7 ... 2025-07-30 14:37:02 +02:00
705f2d640e ... 2025-07-30 14:27:06 +02:00
0eb4dd38f8 ... 2025-07-30 14:19:16 +02:00
6233961371 ... 2025-07-30 14:01:29 +02:00
ddfb48f7ab Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-07-30 13:53:56 +02:00
800133ab89 .. 2025-07-30 13:53:54 +02:00
Mahmoud-Emad
2319912f8f refactor: Simplify site.config_meta action handling
- Replace `plbook.find` loop with direct `action_get`
- Standardize on single quotes for string arguments
- Adjust spacing around variable assignment operator
- Simplify PlayBook type hint
2025-07-30 14:53:31 +03:00
0363e5e661 .. 2025-07-30 13:49:57 +02:00
d2bf58f514 ... 2025-07-30 13:19:17 +02:00
bc92114918 ... 2025-07-30 13:15:09 +02:00
f143e3cf48 ... 2025-07-30 13:01:20 +02:00
f20f5efcb6 ... 2025-07-30 13:00:26 +02:00
1d383faa62 ... 2025-07-30 12:57:32 +02:00
46e425cbc5 Merge branch 'development' of github.com:freeflowuniverse/herolib into development 2025-07-30 12:53:01 +02:00
44d3edca55 ... 2025-07-30 12:52:59 +02:00
Mahmoud-Emad
a44072bd4d fix: add error propagation to git operations
- Add error propagation `!` to git method calls
- Handle potential errors from `gittools.get` and `gs.load`
- Adjust playbook import statement
- Remove unnecessary blank line

Merge branch 'development' of https://github.com/freeflowuniverse/herolib into development
2025-07-30 13:48:36 +03:00
Mahmoud-Emad
957d977147 fix: add error propagation to git operations
- Add error propagation `!` to git method calls
- Handle potential errors from `gittools.get` and `gs.load`
- Adjust playbook import statement
- Remove unnecessary blank line
2025-07-30 13:47:52 +03:00
c038334e67 ... 2025-07-30 12:47:49 +02:00
2f450f7b9b ... 2025-07-30 12:42:53 +02:00
Omdanii
a840d1211a Merge pull request #96 from freeflowuniverse/development_mcp_server
Development mcp server
2025-07-29 20:05:25 +03:00
Mahmoud-Emad
f8dc42499b Merge branch 'development' into development_mcp_server 2025-07-29 20:05:00 +03:00
Mahmoud-Emad
78c5a7a3c6 feat: add SSE endpoint for streaming updates
- Add `/sse` endpoint for Server-Sent Events
- Handle SSE connection in a separate thread
- Periodically stream capabilities and tools list
- Send keepalive pings to maintain connection
2025-07-29 20:03:50 +03:00
Omdanii
983908e531 Merge pull request #95 from freeflowuniverse/development_mcp_server
Add HTTP/REST Transport Support to MCP Framework
2025-07-28 16:13:16 +03:00
Mahmoud-Emad
a76dfc3a28 Merge branch 'development' into development_mcp_server 2025-07-28 15:14:24 +03:00
Mahmoud-Emad
914cba5388 feat: add HTTP/REST transport for MCP servers
- Refactor server to use a generic transport interface
- Add HttpTransport for JSON-RPC and REST over HTTP
- Move existing STDIO logic into a StdioTransport
- Enable dual-mode (STDIO/HTTP) via command-line flags
- Add new examples and docs for HTTP server usage
2025-07-28 13:32:01 +03:00
4c7654fb3c ... 2025-07-28 10:42:27 +02:00
5b48304fac ... 2025-07-28 10:20:13 +02:00
Mahmoud-Emad
6357ae43db feat: add complete V server example and improve runner
- Create new `server.vsh` example with custom tools
- Update `example.sh` to use the new V server script
- Improve README with new, clearer running instructions
- Fix server to not send responses for notifications
- Remove debug logging statements from server and handler
2025-07-27 16:01:28 +03:00
ab5430ddc7 ... 2025-07-25 14:08:44 +02:00
6877de4626 ... 2025-07-25 13:35:30 +02:00
181a81a84a .... 2025-07-25 13:25:48 +02:00
f2079c7c3d ... 2025-07-25 11:05:30 +02:00
9b86f76eaa ... 2025-07-25 10:47:17 +02:00
Mahmoud-Emad
5cee9a4d5a refactor: Extract git repository management into a dedicated module
- Moved git repository handling logic from `gittools` to a new
  `gitresolver` module for better code organization and reusability.
- Created a `GitUrlResolver` interface to abstract git URL resolution.
- Implemented a `GitToolsResolver` struct to adapt the existing
  `gittools` functionality to the new interface.  This allows for
  future extensibility with different git repository management
  strategies.
- Improved error handling and added more informative error messages.
- Improved the structure of the `heroscript` by breaking down the
  actions into smaller, more manageable units.
2025-07-23 19:00:43 +03:00
835556b223 ... 2025-07-23 12:56:13 +02:00
0ebc06589e Merge branch 'development' of github.com:freeflowuniverse/herolib into development
* 'development' of github.com:freeflowuniverse/herolib:
  test: Update EUR/USD exchange rate assumption in tests
  fix: prevent 'img' directory from being ignored
2025-07-23 12:53:29 +02:00
2a23458b57 ... 2025-07-23 11:58:17 +02:00
Mahmoud-Emad
c27862262f test: Update EUR/USD exchange rate assumption in tests
- Updated the assertion for the EUR/USD exchange rate from >= 0.9 to >= 0.8.
- This reflects the current market exchange rate and prevents test failures.
2025-07-22 10:46:24 +03:00
Mahmoud-Emad
5592d13d66 fix: prevent 'img' directory from being ignored
- Prevent the 'img' directory from being incorrectly ignored.
- This ensures that the 'img' directory is processed correctly,
  fixing an issue where it was excluded unintentionally.
2025-07-22 10:29:19 +03:00
63fd9d1660 ... 2025-07-22 09:20:10 +02:00
d59c9a06fd ... 2025-07-22 09:04:42 +02:00
21e43c69a8 ... 2025-07-22 07:39:08 +02:00
b560288962 ... 2025-07-22 07:19:16 +02:00
57dfa87a9e ... 2025-07-21 17:50:37 +02:00
4fb7996f99 ... 2025-07-21 17:29:47 +02:00
bd9cc74c60 ... 2025-07-21 14:29:42 +02:00
ff79c952f2 ... 2025-07-21 13:57:38 +02:00
6c3032e65f ... 2025-07-21 13:42:27 +02:00
740b243356 .. 2025-07-21 13:40:04 +02:00
bb3dd2dbf9 ... 2025-07-21 13:35:30 +02:00
02c4229116 ... 2025-07-21 13:20:24 +02:00
55794a208c ... 2025-07-21 12:53:31 +02:00
c81e342037 ... 2025-07-21 12:50:29 +02:00
1fe0f04226 ... 2025-07-21 12:46:31 +02:00
bf01a35686 ... 2025-07-21 11:57:31 +02:00
1ea0978776 ... 2025-07-21 11:45:23 +02:00
8d7c8e8933 ... 2025-07-21 11:42:19 +02:00
5cc32b3e9c ... 2025-07-21 11:39:22 +02:00
0b8cba068e ... 2025-07-21 11:18:35 +02:00
8282bdf6d5 ... 2025-07-21 11:16:51 +02:00
b8759d29fb ... 2025-07-21 09:56:01 +02:00
1944d58c9f ... 2025-07-21 07:27:17 +02:00
959c1319e7 ... 2025-07-21 06:51:13 +02:00
a538b2af90 ... 2025-07-21 06:47:31 +02:00
0ec8fd58d2 ... 2025-07-21 06:45:50 +02:00
bd120180ea ... 2025-07-21 06:42:00 +02:00
2127fb2ec0 ... 2025-07-21 06:30:42 +02:00
ddf5fcbbcc ... 2025-07-21 06:18:46 +02:00
62932976dd ... 2025-07-20 16:01:09 +02:00
63217506dd ... 2025-07-20 15:57:36 +02:00
fdd619df85 ... 2025-07-20 15:52:46 +02:00
90fc08a816 ... 2025-07-20 15:29:42 +02:00
874ad25fe1 ... 2025-07-20 14:58:06 +02:00
35c3dd7955 ... 2025-07-20 11:23:32 +02:00
b6935cf673 ... 2025-07-20 11:04:10 +02:00
cbde29a8b4 ... 2025-07-20 10:31:19 +02:00
8e47487a23 ... 2025-07-20 06:21:14 +02:00
32fcda82e7 ... 2025-07-19 21:52:05 +02:00
721352489d ... 2025-07-19 21:48:11 +02:00
6092143ed8 ... 2025-07-19 21:19:00 +02:00
d469869b14 ... 2025-07-19 21:09:30 +02:00
391283159d ... 2025-07-19 21:09:16 +02:00
802dcdb8ac ... 2025-07-19 21:02:28 +02:00
a5146e4a27 ... 2025-07-19 20:58:32 +02:00
2c8daf11d8 ... 2025-07-19 19:51:08 +02:00
e798187b89 ... 2025-07-19 19:02:18 +02:00
b9eb75d13e ... 2025-07-19 18:18:46 +02:00
d32f0f4245 ... 2025-07-19 17:27:25 +02:00
e8d4d0afe6 ... 2025-07-19 17:08:33 +02:00
555272eeb3 ... 2025-07-19 16:19:21 +02:00
f53a1c3349 ... 2025-07-19 15:58:50 +02:00
02ffc71aea ... 2025-07-19 15:54:23 +02:00
f092095e7b ... 2025-07-19 13:49:10 +02:00
45c64b8184 ... 2025-07-18 08:06:03 +02:00
1fdd30c147 ... 2025-07-18 07:35:18 +02:00
8354ba4c8c ... 2025-07-18 07:04:00 +02:00
d9f1c93a01 ... 2025-07-18 06:17:57 +02:00
0e7ea1a6f0 ... 2025-07-18 05:55:23 +02:00
9ca0728929 ... 2025-07-18 05:40:57 +02:00
7ea0a43b0c ... 2025-07-18 05:15:30 +02:00
c3b517c4f3 ... 2025-07-17 20:29:11 +04:00
09dedf9669 ... 2025-07-17 20:25:17 +04:00
1b03a9ef6d ... 2025-07-17 20:18:24 +04:00
6ba074b29c ... 2025-07-17 19:50:05 +04:00
731c4a801a ... 2025-07-17 19:15:00 +04:00
0662b37915 ... 2025-07-12 20:37:13 +04:00
545fd75d71 ... 2025-07-12 16:48:50 +04:00
ca6fc6f7a5 ... 2025-07-12 12:28:01 +03:00
49bd1b84ff ... 2025-07-11 20:41:50 +03:00
Omdanii
6a22412a72 Merge pull request #93 from freeflowuniverse/development_docusaurus
feat: Add logo to navbar and update dependencies
2025-06-22 19:22:22 +03:00
Omdanii
35ae33f32a Merge pull request #94 from freeflowuniverse/development_hero_docusaurus
feat: Allow specifying host and port for dev servers
2025-06-22 19:21:47 +03:00
Mahmoud-Emad
e2aa9e7c46 feat: Improve Docusaurus dev server experience
- Stream server logs to the terminal for better monitoring.
- Run the server in a background screen session for persistence.
- Provide clearer instructions for managing the server.
- Improve error handling and fallback mechanisms.
2025-06-22 19:20:43 +03:00
Mahmoud-Emad
dbf18c7a34 feat: Allow specifying host and port for dev servers
- Updated `dev()` methods in Docusaurus and Starlight to accept
  host and port arguments, defaulting to `localhost:3000`.
- This allows more flexibility in development server setup.
- Updated example scripts to use the new parameters.
2025-06-22 15:34:03 +03:00
Mahmoud-Emad
8902d92534 feat: Add logo to navbar and update dependencies
- Added logo to the navbar for improved branding.
- Added `echarts` dependency for enhanced charting capabilities.
- Updated `play.v` to support logo configuration in the menu.
2025-06-17 13:43:30 +03:00
Mahmoud-Emad
483b6e3de3 bump version to 1.0.26 2025-06-17 09:51:38 +03:00
f769c34466 Merge branch 'development_griddriver' into development
* development_griddriver:
  Update griddriver to use prebuilt binary
2025-06-17 08:02:22 +02:00
Mahmoud-Emad
c0242a0729 Merge branch 'development' of https://github.com/freeflowuniverse/herolib into development 2025-06-16 14:04:21 +03:00
Mahmoud-Emad
df452ce258 feat: Add mermaid diagrams support to documentation
- Added support for rendering mermaid diagrams in documentation.
- Updated Docusaurus configuration to include mermaid theme and enable
  mermaid rendering in markdown files.
- Updated package.json dependencies to use compatible versions.
2025-06-16 14:04:10 +03:00
7de290ae55 Merge branch 'dify_installer' into development
* dify_installer:
  dify installer
  dify installer
  adding dify installer
  feat: Improve Dify installer
  adding dify installer
  dify installer
  adding dify installer
  feat: Improve Dify installer
  adding dify installer
2025-06-16 10:21:39 +02:00
fe161c5bea Merge branch 'development_fix_zinit' into development
* development_fix_zinit:
  feat: Fix type mismatch error in rpc.discover response handling
2025-06-16 10:21:26 +02:00
Mahmoud-Emad
fca7c7364a docs: Remove redundant line in README
- Removed a trailing empty line in the README file.
2025-06-16 11:09:16 +03:00
Omdanii
ef705d1be0 Merge pull request #91 from freeflowuniverse/development_mecelium_rpc_client
feat: Add Mycelium JSON-RPC client
2025-06-16 10:51:31 +03:00
Omdanii
3154733be1 Merge pull request #92 from freeflowuniverse/development_zinit_rpc_client
feat: Add Zinit JSON-RPC client
2025-06-16 10:51:13 +03:00
b285e85eb5 Merge branch 'development' of github.com:freeflowuniverse/herolib into development
* 'development' of github.com:freeflowuniverse/herolib:
  feat: Improve ZinitClient and JSON-RPC client
2025-06-15 16:30:46 +02:00
89b7f0d465 ... 2025-06-15 16:30:40 +02:00
Mahmoud-Emad
256d4e9bca feat: Add Zinit RPC client
- Adds a new V client for interacting with the Zinit JSON-RPC API.
- Includes comprehensive example demonstrating all API methods.
- Provides type-safe structs and error handling.
- Implements all 18 methods of the Zinit JSON-RPC API.
2025-06-03 11:11:46 +03:00
Mahmoud-Emad
54f4e83627 Merge branch 'development' into development_mecelium_rpc_client 2025-06-02 17:05:15 +03:00
Mahmoud-Emad
f7a770989b feat: Improve ZinitClient and JSON-RPC client
- Enhanced error handling and response parsing in `ZinitClient`: The
  `discover` function now provides more robust error handling and
  response parsing, improving reliability.
- Improved code style and formatting: Minor formatting changes for
  better readability and maintainability.  The `ServiceConfig` and
  `ServiceConfigResponse` structs have been slightly restructured.
- Updated JSON-RPC client structure: The `Client` struct is now
  publicly mutable (`pub mut`), simplifying its use.  Removed
  unnecessary blank lines for improved code clarity.
2025-06-02 17:04:25 +03:00
Mahmoud-Emad
c5759ea30e feat: Add Mycelium JSON-RPC client
- Adds a new V language client for interacting with the Mycelium
  JSON-RPC admin API.
- Includes comprehensive example code demonstrating all API features.
- Implements all methods defined in the Mycelium JSON-RPC spec.
- Provides type-safe API with robust error handling.
- Uses HTTP transport for communication with the Mycelium node.
2025-06-02 16:48:59 +03:00
Mahmoud-Emad
aef9c84eb5 feat: Fix type mismatch error in rpc.discover response handling
- Correctly handle the complex JSON response of the `rpc.discover`
  method by using `map[string]string` instead of `string`.  This
  addresses a type mismatch error that prevented proper parsing of
  the API specification.
- Improve error handling and provide more informative output to the
  user during the API discovery process.
- Add detailed analysis and recommendations for handling complex JSON
  responses in similar scenarios.
2025-06-01 15:09:57 +03:00
d0baac83a9 ... 2025-05-31 16:02:52 +03:00
b6a2671665 ... 2025-05-31 12:45:05 +03:00
a96ae1252c ... 2025-05-31 11:17:56 +03:00
ac4db0f789 rpc example 2025-05-31 11:05:59 +03:00
37f9ab78ec format, implement unixsocket rpc 2025-05-31 08:26:03 +03:00
timurgordon
9b3ac150bd Merge branch 'development' of https://github.com/freeflowuniverse/herolib into development 2025-05-29 23:10:17 +03:00
timurgordon
dd577d51b9 match template and models for docusaurus 2025-05-29 23:10:13 +03:00
92f9714229 ... 2025-05-29 20:22:52 +04:00
timurgordon
632a1c11c2 fix docusaurus to use siteconfig in heroscript 2025-05-29 17:31:51 +03:00
Peternashaat
63d41352bc adding dify installer 2025-05-29 13:23:41 +00:00
Peternashaat
da8eef3711 dify installer 2025-05-29 13:06:36 +00:00
Peternashaat
f0a4732206 dify installer 2025-05-29 13:09:46 +03:00
Peternashaat
1f053edefc adding dify installer 2025-05-29 13:09:46 +03:00
Mahmoud-Emad
f93db1d23c feat: Improve Dify installer
- Update installer configuration to be more robust and flexible.
- Remove unnecessary installation steps in the installer script.
- Improve the installer's ability to check if Dify is running.
- Refactor Dify installer actions for better code organization.
- Add build functionality to Dify installer.
2025-05-29 13:09:46 +03:00
Peternashaat
105611bbfb adding dify installer 2025-05-29 13:09:46 +03:00
Peternashaat
4977c6de30 dify installer 2025-05-28 07:07:53 +00:00
Peternashaat
eb956bca3d adding dify installer 2025-05-27 11:40:50 +00:00
Mahmoud-Emad
5e511367c3 feat: Improve Dify installer
- Update installer configuration to be more robust and flexible.
- Remove unnecessary installation steps in the installer script.
- Improve the installer's ability to check if Dify is running.
- Refactor Dify installer actions for better code organization.
- Add build functionality to Dify installer.
2025-05-27 12:33:25 +03:00
Peternashaat
484bfe393e adding dify installer 2025-05-27 09:05:08 +00:00
a1404584d6 ... 2025-05-25 06:47:17 +04:00
3ef1698c2c ... 2025-05-25 06:44:51 +04:00
a7fb704627 ... 2025-05-25 06:30:48 +04:00
91ba6001cb ... 2025-05-22 20:12:06 +04:00
345a79d8ff ... 2025-05-21 09:05:30 +04:00
15d886e5e9 ... 2025-05-21 09:00:30 +04:00
d6224d1e60 ... 2025-05-21 08:56:34 +04:00
83fb647ac3 ... 2025-05-21 08:37:02 +04:00
b410544ee1 ... 2025-05-21 08:30:30 +04:00
2d5d1befae ... 2025-05-20 09:48:56 +04:00
fd8b8c8f42 revert 2025-05-20 07:00:00 +04:00
8ffb8c8caf ... 2025-05-20 06:49:39 +04:00
b8b339b85c ... 2025-05-20 06:47:36 +04:00
0789a38ea9 Merge branch 'development' of github.com:freeflowuniverse/herolib into development
# Conflicts:
#	lib/web/docusaurus/dsite.v
2025-05-20 06:40:48 +04:00
995d3c3f6d ... 2025-05-20 06:39:40 +04:00
timurgordon
822b179ef4 docusaurus fixes 2025-05-19 11:19:19 +03:00
4691971bd0 ... 2025-05-19 09:07:38 +04:00
9226e8b490 ... 2025-05-19 08:56:15 +04:00
b7fc7734b6 ... 2025-05-19 08:52:09 +04:00
8749e3a8cb ... 2025-05-19 08:52:03 +04:00
61f9f2868a ... 2025-05-19 08:25:47 +04:00
97dfcbeb51 ... 2025-05-19 07:37:10 +04:00
238fabbcb2 ... 2025-05-19 07:09:27 +04:00
49542b4bff ... 2025-05-19 07:04:20 +04:00
46898112f5 ... 2025-05-19 06:39:52 +04:00
f9bdb22c67 ... 2025-05-19 05:44:23 +04:00
cb664b2115 ... 2025-05-18 10:58:49 +03:00
timurgordon
761b9e031e docusaurus fixes 2025-05-16 18:03:22 +03:00
timurgordon
0d8d11fe26 small heroscript docusaurus fixes 2025-05-15 13:29:29 +03:00
timurgordon
2d5fbd3337 docusaurus fixes and correct hero cli implementation 2025-05-13 01:54:47 +03:00
cd3c98280e ... 2025-05-09 12:53:08 +03:00
Scott Yeager
54dc3d3f1f Update griddriver to use prebuilt binary 2025-03-06 18:26:33 -08:00
1525 changed files with 136135 additions and 32114 deletions

View File

@@ -24,9 +24,9 @@ jobs:
- target: aarch64-apple-darwin
os: macos-latest
short-name: macos-arm64
- target: x86_64-apple-darwin
os: macos-13
short-name: macos-i64
# - target: x86_64-apple-darwin
# os: macos-13
# short-name: macos-i64
runs-on: ${{ matrix.os }}
steps:
@@ -34,6 +34,10 @@ jobs:
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref_name }} and your repository is ${{ github.repository }}."
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Check out repository code
uses: actions/checkout@v4
@@ -42,10 +46,9 @@ jobs:
run: ./install_v.sh --herolib
timeout-minutes: 10
- name: Do all the basic tests
timeout-minutes: 25
run: ./test_basic.vsh
# - name: Do all the basic tests
# timeout-minutes: 25
# run: ./test_basic.vsh
- name: Build Hero
timeout-minutes: 15

8
.gitignore vendored
View File

@@ -47,3 +47,11 @@ tmp
compile_summary.log
.summary_lock
.aider*
*.dylib
server
HTTP_REST_MCP_DEMO.md
MCP_HTTP_REST_IMPLEMENTATION_PLAN.md
.roo
.kilocode
.continue
tmux_logger

6
.zed/keymap.json Normal file
View File

@@ -0,0 +1,6 @@
{
"context": "Workspace",
"bindings": {
"cmd-r": ["task::Spawn", { "task_name": "ET", "reveal_target": "center" }]
}
}

47
.zed/tasks.json Normal file
View File

@@ -0,0 +1,47 @@
[
{
"label": "ET",
"command": "for i in {1..5}; do echo \"Hello $i/5\"; sleep 1; done",
//"args": [],
// Env overrides for the command, will be appended to the terminal's environment from the settings.
"env": { "foo": "bar" },
// Current working directory to spawn the command into, defaults to current project root.
//"cwd": "/path/to/working/directory",
// Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
"use_new_terminal": true,
// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
"allow_concurrent_runs": false,
// What to do with the terminal pane and tab, after the command was started:
// * `always` — always show the task's pane, and focus the corresponding tab in it (default)
// * `no_focus` — always show the task's pane, add the task's tab in it, but don't focus it
// * `never` — do not alter focus, but still add/reuse the task's tab in its pane
"reveal": "always",
// What to do with the terminal pane and tab, after the command has finished:
// * `never` — Do nothing when the command finishes (default)
// * `always` — always hide the terminal tab, hide the pane also if it was the last tab in it
// * `on_success` — hide the terminal tab on task success only, otherwise behaves similar to `always`
"hide": "never",
// Which shell to use when running a task inside the terminal.
// May take 3 values:
// 1. (default) Use the system's default terminal configuration in /etc/passwd
// "shell": "system"
// 2. A program:
// "shell": {
// "program": "sh"
// }
// 3. A program with arguments:
// "shell": {
// "with_arguments": {
// "program": "/bin/bash",
// "args": ["--login"]
// }
// }
"shell": "system",
// Whether to show the task line in the output of the spawned task, defaults to `true`.
"show_summary": true,
// Whether to show the command line in the output of the spawned task, defaults to `true`.
// "show_output": true,
// Represents the tags for inline runnable indicators, or spawning multiple tasks at once.
"tags": ["DODO"]
}
]

View File

@@ -7,17 +7,6 @@ Herolib is an opinionated library primarily used by ThreeFold to automate cloud
> [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
## Table of Contents
- [Installation](#installation)
- [For Users](#for-users)
- [For Developers](#for-developers)
- [Features](#features)
- [Testing](#testing)
- [Contributing](#contributing)
- [Troubleshooting](#troubleshooting)
- [Additional Resources](#additional-resources)
## Installation
### For Users
@@ -25,19 +14,17 @@ Herolib is an opinionated library primarily used by ThreeFold to automate cloud
The Hero tool can be installed with a single command:
```bash
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
bash /tmp/install_hero.sh
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh | bash
```
Hero will be installed in:
- `/usr/local/bin` for Linux
- `~/hero/bin` for macOS
After installation on macOS, you may need to:
After installation on macOS, you may need to do source see below or restart your terminal to ensure the `hero` command is available:
```bash
source ~/.zprofile
# Or copy to system bin directory
cp ~/hero/bin/hero /usr/local/bin
```
The Hero tool can be used to work with git, build documentation, interact with Hero AI, and more.
@@ -49,7 +36,13 @@ For development purposes, use the automated installation script:
```bash
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_v.sh' > /tmp/install_v.sh
bash /tmp/install_v.sh --analyzer --herolib
#do not forget to do the following this makes sure vtest and vrun exists
cd ~/code/github/freeflowuniverse/herolib
bash install_herolib.vsh
# IMPORTANT: Start a new shell after installation for paths to be set correctly
```
#### Installation Options
@@ -81,6 +74,17 @@ Herolib provides a wide range of functionality:
- Cloud automation tools
- Git operations and management
### Offline Mode for Git Operations
Herolib now supports an `offline` mode for Git operations, which prevents automatic fetching from remote repositories. This can be useful in environments with limited or no internet connectivity, or when you want to avoid network calls during development or testing.
To enable offline mode:
- **Via `GitStructureConfig`**: Set the `offline` field to `true` in the `GitStructureConfig` struct.
- **Via `GitStructureArgsNew`**: When creating a new `GitStructure` instance using `gittools.new()`, set the `offline` parameter to `true`.
- **Via Environment Variable**: Set the `OFFLINE` environment variable to any value (e.g., `export OFFLINE=true`).
When offline mode is active, `git fetch --all` operations will be skipped, and a debug message "fetch skipped (offline)" will be printed.
- Documentation building
- Hero AI integration
- System management utilities
@@ -167,3 +171,6 @@ To generate documentation locally:
cd ~/code/github/freeflowuniverse/herolib
bash doc.sh
```
<!-- Security scan triggered at 2025-09-02 01:58:41 -->

View File

@@ -0,0 +1,19 @@
#!/bin/bash
# Herolib Web Server Installation Script
# This script sets up the necessary environment for the Flask web server.
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
/workspace/herolib/install_v.sh

View File

@@ -1,204 +0,0 @@
# instructions how to work with heroscript in vlang
## heroscript
Heroscript is our small scripting language which has following structure
an example of a heroscript is
```heroscript
!!mailclient.configure
name: 'myname'
host: 'localhost'
port: 25
secure: 1
reset: 1
description: '
a description can be multiline
like this
'
```
Notice how:
- every action starts with !!
- the first part is the actor, mailclient in this case
- the 2e part is the action name, configure in this case
- multilines are supported see the description field
## how to process heroscript in Vlang
- heroscript can be converted to a struct,
- the methods available to get the params are in 'params' section further in this doc
```vlang
//the object which will be configured
pub struct mailclient {
pub mut:
name string
host string
port int
secure bool
description string
}
mut plbook := playbook.new(text: $the_heroscript_from_above)!
play_mailclient(mut plbook)! //see below in vlang block there it all happens
pub fn play_mailclient(mut plbook playbook.PlayBook) ! {
//find all actions are !!$actor.$actionname. in this case above the actor is !!mailclient, we check with the fitler if it exists, if not we return
mailclient_actions := plbook.find(filter: 'mailclient.')!
for action in mailclient_actions {
if action.name == "configure"{
mut p := action.params
mut obj := mailclientScript{
//INFO: all details about the get methods can be found in 'params get methods' section
name : p.get('name')! //will give error if not exist
homedir : p.get('homedir')!
title : p.get_default('title', 'My Hero DAG')! //uses a default if not set
reset : p.get_default_false('reset')
start : p.get_default_true('start')
colors : p.get_list('colors')
description : p.get_default('description','')!
}
}
}
}
}
## params get methods (param getters)
above in the p.get...
below you can find the methods which can be used on the params
```vlang
exists(key_ string) bool
//check if arg exist (arg is just a value in the string e.g. red, not value:something)
exists_arg(key_ string) bool
//see if the kwarg with the key exists if yes return as string trimmed
get(key_ string) !string
//return the arg with nr, 0 is the first
get_arg(nr int) !string
//return arg, if the nr is larger than amount of args, will return the defval
get_arg_default(nr int, defval string) !string
get_default(key string, defval string) !string
get_default_false(key string) bool
get_default_true(key string) bool
get_float(key string) !f64
get_float_default(key string, defval f64) !f64
get_from_hashmap(key_ string, defval string, hashmap map[string]string) !string
get_int(key string) !int
get_int_default(key string, defval int) !int
//Looks for a list of strings in the parameters. ',' are used as deliminator to list
get_list(key string) ![]string
get_list_default(key string, def []string) ![]string
get_list_f32(key string) ![]f32
get_list_f32_default(key string, def []f32) []f32
get_list_f64(key string) ![]f64
get_list_f64_default(key string, def []f64) []f64
get_list_i16(key string) ![]i16
get_list_i16_default(key string, def []i16) []i16
get_list_i64(key string) ![]i64
get_list_i64_default(key string, def []i64) []i64
get_list_i8(key string) ![]i8
get_list_i8_default(key string, def []i8) []i8
get_list_int(key string) ![]int
get_list_int_default(key string, def []int) []int
get_list_namefix(key string) ![]string
get_list_namefix_default(key string, def []string) ![]string
get_list_u16(key string) ![]u16
get_list_u16_default(key string, def []u16) []u16
get_list_u32(key string) ![]u32
get_list_u32_default(key string, def []u32) []u32
get_list_u64(key string) ![]u64
get_list_u64_default(key string, def []u64) []u64
get_list_u8(key string) ![]u8
get_list_u8_default(key string, def []u8) []u8
get_map() map[string]string
get_path(key string) !string
get_path_create(key string) !string
get_percentage(key string) !f64
get_percentage_default(key string, defval string) !f64
//convert GB, MB, KB to bytes e.g. 10 GB becomes bytes in u64
get_storagecapacity_in_bytes(key string) !u64
get_storagecapacity_in_bytes_default(key string, defval u64) !u64
get_storagecapacity_in_gigabytes(key string) !u64
//Get Expiration object from time string input input can be either relative or absolute## Relative time
get_time(key string) !ourtime.OurTime
get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime
get_time_interval(key string) !Duration
get_timestamp(key string) !Duration
get_timestamp_default(key string, defval Duration) !Duration
get_u32(key string) !u32
get_u32_default(key string, defval u32) !u32
get_u64(key string) !u64
get_u64_default(key string, defval u64) !u64
get_u8(key string) !u8
get_u8_default(key string, defval u8) !u8
```

View File

@@ -1,142 +0,0 @@
# how to use params
works very well in combination with heroscript
## How to get the paramsparser
```v
import freeflowuniverse.herolib.data.paramsparser
// Create new params from text
params := paramsparser.new("color:red size:'large' priority:1 enable:true")!
// Or create empty params and add later
mut params := paramsparser.new_params()
params.set("color", "red")
```
## Parameter Format
The parser supports several formats:
1. Key-value pairs: `key:value`
2. Quoted values: `key:'value with spaces'`
3. Arguments without keys: `arg1 arg2`
4. Comments: `// this is a comment`
Example:
```v
text := "name:'John Doe' age:30 active:true // user details"
params := paramsparser.new(text)!
```
## Getting Values
The module provides various methods to retrieve values:
```v
// Get string value
name := params.get("name")! // returns "John Doe"
// Get with default value
color := params.get_default("color", "blue")! // returns "blue" if color not set
// Get as integer
age := params.get_int("age")! // returns 30
// Get as boolean (true if value is "1", "true", "y", "yes")
is_active := params.get_default_true("active")
// Get as float
score := params.get_float("score")!
// Get as percentage (converts "80%" to 0.8)
progress := params.get_percentage("progress")!
```
## Type Conversion Methods
The module supports various type conversions:
### Basic Types
- `get_int()`: Convert to int32
- `get_u32()`: Convert to unsigned 32-bit integer
- `get_u64()`: Convert to unsigned 64-bit integer
- `get_u8()`: Convert to unsigned 8-bit integer
- `get_float()`: Convert to 64-bit float
- `get_percentage()`: Convert percentage string to float (e.g., "80%" → 0.8)
### Boolean Values
- `get_default_true()`: Returns true if value is empty, "1", "true", "y", or "yes"
- `get_default_false()`: Returns false if value is empty, "0", "false", "n", or "no"
### Lists
The module provides robust support for parsing and converting lists:
```v
// Basic list parsing
names := params.get_list("users")! // parses ["user1", "user2", "user3"]
// With default value
tags := params.get_list_default("tags", ["default"])!
// Lists with type conversion
numbers := params.get_list_int("ids")! // converts each item to int
amounts := params.get_list_f64("prices")! // converts each item to f64
// Name-fixed lists (normalizes each item)
clean_names := params.get_list_namefix("categories")!
```
Supported list types:
- `get_list()`: String list
- `get_list_u8()`, `get_list_u16()`, `get_list_u32()`, `get_list_u64()`: Unsigned integers
- `get_list_i8()`, `get_list_i16()`, `get_list_int()`, `get_list_i64()`: Signed integers
- `get_list_f32()`, `get_list_f64()`: Floating point numbers
Each list method has a corresponding `_default` version that accepts a default value.
Valid list formats:
```v
users: "john, jane,bob"
ids: "1,2,3,4,5"
```
### Advanced
```v
get_map() map[string]string
get_path(key string) !string
get_path_create(key string) !string //will create path if it doesnt exist yet
get_percentage(key string) !f64
get_percentage_default(key string, defval string) !f64
//convert GB, MB, KB to bytes e.g. 10 GB becomes bytes in u64
get_storagecapacity_in_bytes(key string) !u64
get_storagecapacity_in_bytes_default(key string, defval u64) !u64
get_storagecapacity_in_gigabytes(key string) !u64
//Get Expiration object from time string input input can be either relative or absolute## Relative time
get_time(key string) !ourtime.OurTime
get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime
get_time_interval(key string) !Duration
get_timestamp(key string) !Duration
get_timestamp_default(key string, defval Duration) !Duration
```

View File

@@ -1,309 +0,0 @@
# how to work with heroscript in vlang
## heroscript
Heroscript is our small scripting language which has following structure
an example of a heroscript is
```heroscript
!!dagu.script_define
name: 'test_dag'
homedir:''
title:'a title'
reset:1
start:true //trie or 1 is same
colors: 'green,red,purple' //lists are comma separated
description: '
a description can be multiline
like this
'
!!dagu.add_step
dag: 'test_dag'
name: 'hello_world'
command: 'echo hello world'
!!dagu.add_step
dag: 'test_dag'
name: 'last_step'
command: 'echo last step'
```
Notice how:
- every action starts with !!
- the first part is the actor e.g. dagu in this case
- the 2e part is the action name
- multilines are supported see the description field
## how to process heroscript in Vlang
- heroscript can be converted to a struct,
- the methods available to get the params are in 'params' section further in this doc
```vlang
fn test_play_dagu() ! {
mut plbook := playbook.new(text: thetext_from_above)!
play_dagu(mut plbook)! //see below in vlang block there it all happens
}
pub fn play_dagu(mut plbook playbook.PlayBook) ! {
//find all actions are !!$actor.$actionname. in this case above the actor is !!dagu, we check with the fitler if it exists, if not we return
dagu_actions := plbook.find(filter: 'dagu.')!
if dagu_actions.len == 0 {
return
}
play_dagu_basic(mut plbook)!
}
pub struct DaguScript {
pub mut:
name string
homedir string
title string
reset bool
start bool
colors []string
}
// play_dagu plays the dagu play commands
pub fn play_dagu_basic(mut plbook playbook.PlayBook) ! {
//now find the specific ones for dagu.script_define
mut actions := plbook.find(filter: 'dagu.script_define')!
if actions.len > 0 {
for myaction in actions {
mut p := myaction.params //get the params object from the action object, this can then be processed using the param getters
mut obj := DaguScript{
//INFO: all details about the get methods can be found in 'params get methods' section
name : p.get('name')! //will give error if not exist
homedir : p.get('homedir')!
title : p.get_default('title', 'My Hero DAG')! //uses a default if not set
reset : p.get_default_false('reset')
start : p.get_default_true('start')
colors : p.get_list('colors')
description : p.get_default('description','')!
}
...
}
}
//there can be more actions which will have other filter
}
```
## params get methods (param getters)
```vlang
fn (params &Params) exists(key_ string) bool
//check if arg exist (arg is just a value in the string e.g. red, not value:something)
fn (params &Params) exists_arg(key_ string) bool
//see if the kwarg with the key exists if yes return as string trimmed
fn (params &Params) get(key_ string) !string
//return the arg with nr, 0 is the first
fn (params &Params) get_arg(nr int) !string
//return arg, if the nr is larger than amount of args, will return the defval
fn (params &Params) get_arg_default(nr int, defval string) !string
fn (params &Params) get_default(key string, defval string) !string
fn (params &Params) get_default_false(key string) bool
fn (params &Params) get_default_true(key string) bool
fn (params &Params) get_float(key string) !f64
fn (params &Params) get_float_default(key string, defval f64) !f64
fn (params &Params) get_from_hashmap(key_ string, defval string, hashmap map[string]string) !string
fn (params &Params) get_int(key string) !int
fn (params &Params) get_int_default(key string, defval int) !int
//Looks for a list of strings in the parameters. ',' are used as deliminator to list
fn (params &Params) get_list(key string) ![]string
fn (params &Params) get_list_default(key string, def []string) ![]string
fn (params &Params) get_list_f32(key string) ![]f32
fn (params &Params) get_list_f32_default(key string, def []f32) []f32
fn (params &Params) get_list_f64(key string) ![]f64
fn (params &Params) get_list_f64_default(key string, def []f64) []f64
fn (params &Params) get_list_i16(key string) ![]i16
fn (params &Params) get_list_i16_default(key string, def []i16) []i16
fn (params &Params) get_list_i64(key string) ![]i64
fn (params &Params) get_list_i64_default(key string, def []i64) []i64
fn (params &Params) get_list_i8(key string) ![]i8
fn (params &Params) get_list_i8_default(key string, def []i8) []i8
fn (params &Params) get_list_int(key string) ![]int
fn (params &Params) get_list_int_default(key string, def []int) []int
fn (params &Params) get_list_namefix(key string) ![]string
fn (params &Params) get_list_namefix_default(key string, def []string) ![]string
fn (params &Params) get_list_u16(key string) ![]u16
fn (params &Params) get_list_u16_default(key string, def []u16) []u16
fn (params &Params) get_list_u32(key string) ![]u32
fn (params &Params) get_list_u32_default(key string, def []u32) []u32
fn (params &Params) get_list_u64(key string) ![]u64
fn (params &Params) get_list_u64_default(key string, def []u64) []u64
fn (params &Params) get_list_u8(key string) ![]u8
fn (params &Params) get_list_u8_default(key string, def []u8) []u8
fn (params &Params) get_map() map[string]string
fn (params &Params) get_path(key string) !string
fn (params &Params) get_path_create(key string) !string
fn (params &Params) get_percentage(key string) !f64
fn (params &Params) get_percentage_default(key string, defval string) !f64
//convert GB, MB, KB to bytes e.g. 10 GB becomes bytes in u64
fn (params &Params) get_storagecapacity_in_bytes(key string) !u64
fn (params &Params) get_storagecapacity_in_bytes_default(key string, defval u64) !u64
fn (params &Params) get_storagecapacity_in_gigabytes(key string) !u64
//Get Expiration object from time string input input can be either relative or absolute## Relative time
fn (params &Params) get_time(key string) !ourtime.OurTime
fn (params &Params) get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime
fn (params &Params) get_time_interval(key string) !Duration
fn (params &Params) get_timestamp(key string) !Duration
fn (params &Params) get_timestamp_default(key string, defval Duration) !Duration
fn (params &Params) get_u32(key string) !u32
fn (params &Params) get_u32_default(key string, defval u32) !u32
fn (params &Params) get_u64(key string) !u64
fn (params &Params) get_u64_default(key string, defval u64) !u64
fn (params &Params) get_u8(key string) !u8
fn (params &Params) get_u8_default(key string, defval u8) !u8
```
## how internally a heroscript gets parsed for params
- example to show how a heroscript gets parsed in action with params
- params are part of action object
```heroscript
example text to parse (heroscript)
id:a1 name6:aaaaa
name:'need to do something 1'
description:
'
## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
name2: test
name3: hi
name10:'this is with space' name11:aaa11
name4: 'aaa'
//somecomment
name5: 'aab'
```
the params are part of the action and are represented as follow for the above:
```vlang
Params{
params: [Param{
key: 'id'
value: 'a1'
}, Param{
key: 'name6'
value: 'aaaaa'
}, Param{
key: 'name'
value: 'need to do something 1'
}, Param{
key: 'description'
value: '## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
}, Param{
key: 'name2'
value: 'test'
}, Param{
key: 'name3'
value: 'hi'
}, Param{
key: 'name10'
value: 'this is with space'
}, Param{
key: 'name11'
value: 'aaa11'
}, Param{
key: 'name4'
value: 'aaa'
}, Param{
key: 'name5'
value: 'aab'
}]
}
```

View File

@@ -1,441 +0,0 @@
# module osal
import as
```vlang
import freeflowuniverse.osal
osal.ping...
```
## ping
```go
assert ping(address:"338.8.8.8")==.unknownhost
assert ping(address:"8.8.8.8")==.ok
assert ping(address:"18.8.8.8")==.timeout
```
will do a panic if its not one of them, an unknown error
## platform
```go
if platform()==.osx{
//do something
}
pub enum PlatformType {
unknown
osx
ubuntu
alpine
}
pub enum CPUType {
unknown
intel
arm
intel32
arm32
}
```
## process
### execute jobs
```v
mut job2:=osal.exec(cmd:"ls /")?
println(job2)
//wont die, the result can be found in /tmp/execscripts
mut job:=osal.exec(cmd:"ls dsds",ignore_error:true)?
//this one has an error
println(job)
```
All scripts are executed from a file from /tmp/execscripts
If the script executes well then its removed, so no leftovers, if it fails the script stays in the dir
### check process logs
```
mut pm:=process.processmap_get()?
```
info returns like:
```json
}, freeflowuniverse.process.ProcessInfo{
cpu_perc: 0
mem_perc: 0
cmd: 'mc'
pid: 84455
ppid: 84467
rss: 3168
}, freeflowuniverse.process.ProcessInfo{
cpu_perc: 0
mem_perc: 0
cmd: 'zsh -Z -g'
pid: 84467
ppid: 84469
rss: 1360
}]
```
## other commands
fn bin*path() !string
fn cmd_add(args* CmdAddArgs) !
copy a binary to the right location on the local computer . e.g. is /usr/local/bin on linux . e.g. is ~/hero/bin on osx . will also add the bin location to the path of .zprofile and .zshrc (different per platform)
fn cmd*exists(cmd string) bool
fn cmd_exists_profile(cmd string) bool
fn cmd_path(cmd string) !string
is same as executing which in OS returns path or error
fn cmd_to_script_path(cmd Command) !string
will return temporary path which then can be executed, is a helper function for making script out of command
fn cputype() CPUType
fn cputype_enum_from_string(cpytype string) CPUType
Returns the enum value that matches the provided string for CPUType
fn dir_delete(path string) !
remove all if it exists
fn dir_ensure(path string) !
remove all if it exists
fn dir_reset(path string) !
remove all if it exists and then (re-)create
fn done_delete(key string) !
fn done_exists(key string) bool
fn done_get(key string) ?string
fn done_get_int(key string) int
fn done_get_str(key string) string
fn done_print() !
fn done_reset() !
fn done_set(key string, val string) !
fn download(args* DownloadArgs) !pathlib.Path
if name is not specified, then will be the filename part if the last ends in an extension like .md .txt .log .text ... the file will be downloaded
fn env_get(key string) !string
Returns the requested environment variable if it exists or throws an error if it does not
fn env_get_all() map[string]string
Returns all existing environment variables
fn env_get_default(key string, def string) string
Returns the requested environment variable if it exists or returns the provided default value if it does not
fn env_set(args EnvSet)
Sets an environment if it was not set before, it overwrites the enviroment variable if it exists and if overwrite was set to true (default)
fn env_set_all(args EnvSetAll)
Allows to set multiple enviroment variables in one go, if clear_before_set is true all existing environment variables will be unset before the operation, if overwrite_if_exists is set to true it will overwrite all existing enviromnent variables
fn env_unset(key string)
Unsets an environment variable
fn env_unset_all()
Unsets all environment variables
fn exec(cmd Command) !Job
cmd is the cmd to execute can use ' ' and spaces . if \n in cmd it will write it to ext and then execute with bash . if die==false then will just return returncode,out but not return error . if stdout will show stderr and stdout . . if cmd starts with find or ls, will give to bash -c so it can execute . if cmd has no path, path will be found . . Command argument: .
````
name string // to give a name to your command, good to see logs...
cmd string
description string
timeout int = 3600 // timeout in sec
stdout bool = true
stdout_log bool = true
raise_error bool = true // if false, will not raise an error but still error report
ignore_error bool // means if error will just exit and not raise, there will be no error reporting
work_folder string // location where cmd will be executed
environment map[string]string // env variables
ignore_error_codes []int
scriptpath string // is the path where the script will be put which is executed
scriptkeep bool // means we don't remove the script
debug bool // if debug will put +ex in the script which is being executed and will make sure script stays
shell bool // means we will execute it in a shell interactive
retry int
interactive bool = true // make sure we run on non interactive way
async bool
runtime RunTime (.bash, .python)
returns Job:
start time.Time
end time.Time
cmd Command
output []string
error []string
exit_code int
status JobStatus
process os.Process
```
return Job .
fn exec_string(cmd Command) !string
cmd is the cmd to execute can use ' ' and spaces if \n in cmd it will write it to ext and then execute with bash if die==false then will just return returncode,out but not return error if stdout will show stderr and stdout
if cmd starts with find or ls, will give to bash -c so it can execute if cmd has no path, path will be found $... are remplaced by environment arguments TODO:implement
Command argument: cmd string timeout int = 600 stdout bool = true die bool = true debug bool
return what needs to be executed can give it to bash -c ...
fn execute*debug(cmd string) !string
fn execute_interactive(cmd string) !
shortcut to execute a job interactive means in shell
fn execute_ok(cmd string) bool
executes a cmd, if not error return true
fn execute_silent(cmd string) !string
shortcut to execute a job silent
fn execute_stdout(cmd string) !string
shortcut to execute a job to stdout
fn file_read(path string) !string
fn file_write(path string, text string) !
fn get_logger() log.Logger
Returns a logger object and allows you to specify via environment argument OSAL_LOG_LEVEL the debug level
fn hero_path() !string
fn hostname() !string
fn initname() !string
e.g. systemd, bash, zinit
fn ipaddr_pub_get() !string
Returns the ipaddress as known on the public side is using resolver4.opendns.com
fn is_linux()! bool
fn is_linux_arm()! bool
fn is_linux_intel()! bool
fn is_osx()! bool
fn is_osx_arm()! bool
fn is_osx_intel()! bool
fn is_ubuntu()! bool
fn load_env_file(file_path string) !
fn memdb_exists(key string) bool
fn memdb_get(key string) string
fn memdb_set(key string, val string)
fn package_install(name* string) !
install a package will use right commands per platform
fn package_refresh() !
update the package list
fn ping(args PingArgs) PingResult
if reached in timout result will be True address is e.g. 8.8.8.8 ping means we check if the destination responds
fn platform() PlatformType
fn platform_enum_from_string(platform string) PlatformType
fn process_exists(pid int) bool
fn process_exists_byname(name string) !bool
fn process_kill_recursive(args ProcessKillArgs) !
kill process and all the ones underneith
fn processinfo_children(pid int) !ProcessMap
get all children of 1 process
fn processinfo_get(pid int) !ProcessInfo
get process info from 1 specific process returns
` pub struct ProcessInfo {
pub mut:
cpu_perc f32
mem_perc f32
cmd string
pid int
ppid int
//resident memory
rss int
}
`
fn processinfo_get_byname(name string) ![]ProcessInfo
fn processinfo_with_children(pid int) !ProcessMap
return the process and its children
fn processmap_get() !ProcessMap
make sure to use new first, so that the connection has been initted then you can get it everywhere
fn profile_path() string
fn profile_path_add(args ProfilePathAddArgs) !
add the following path to a profile
fn profile_path_add_hero() !string
fn profile_path_source() string
return the source statement if the profile exists
fn profile_path_source_and() string
return source $path && . or empty if it doesn't exist
fn sleep(duration int)
sleep in seconds
fn tcp_port_test(args TcpPortTestArgs) bool
test if a tcp port answers
` address string //192.168.8.8
port int = 22
timeout u16 = 2000 // total time in milliseconds to keep on trying
`
fn user_add(args UserArgs) !int
add's a user if the user does not exist yet
fn user_exists(username string) bool
fn user_id_get(username string) !int
fn usr_local_path() !string
/usr/local on linux, ${os.home_dir()}/hero on osx
fn whoami() !string
fn write_flags[T](options T) string
enum CPUType {
unknown
intel
arm
intel32
arm32
}
enum ErrorType {
exec
timeout
args
}
enum JobStatus {
init
running
error_exec
error_timeout
error_args
done
}
enum PMState {
init
ok
old
}
enum PingResult {
ok
timeout // timeout from ping
unknownhost // means we don't know the hostname its a dns issue
}
enum PlatformType {
unknown
osx
ubuntu
alpine
arch
suse
}
enum RunTime {
bash
python
heroscript
herocmd
v
}
struct CmdAddArgs {
pub mut:
cmdname string
source string @[required] // path where the binary is
symlink bool // if rather than copy do a symlink
reset bool // if existing cmd will delete
// bin_repo_url string = 'https://github.com/freeflowuniverse/freeflow_binary' // binary where we put the results
}
struct Command {
pub mut:
name string // to give a name to your command, good to see logs...
cmd string
description string
timeout int = 3600 // timeout in sec
stdout bool = true
stdout_log bool = true
raise_error bool = true // if false, will not raise an error but still error report
ignore_error bool // means if error will just exit and not raise, there will be no error reporting
work_folder string // location where cmd will be executed
environment map[string]string // env variables
ignore_error_codes []int
scriptpath string // is the path where the script will be put which is executed
scriptkeep bool // means we don't remove the script
debug bool // if debug will put +ex in the script which is being executed and will make sure script stays
shell bool // means we will execute it in a shell interactive
retry int
interactive bool = true
async bool
runtime RunTime
}
struct DownloadArgs {
pub mut:
name string // optional (otherwise derived out of filename)
url string
reset bool // will remove
hash string // if hash is known, will verify what hash is
dest string // if specified will copy to that destination
timeout int = 180
retry int = 3
minsize_kb u32 = 10 // is always in kb
maxsize_kb u32
expand_dir string
expand_file string
}
struct EnvSet {
pub mut:
key string @[required]
value string @[required]
overwrite bool = true
}
struct EnvSetAll {
pub mut:
env map[string]string
clear_before_set bool
overwrite_if_exists bool = true
}
struct Job {
pub mut:
start time.Time
end time.Time
cmd Command
output string
error string
exit_code int
status JobStatus
process ?&os.Process @[skip; str: skip]
runnr int // nr of time it runs, is for retry
}
fn (mut job Job) execute_retry() !
execute the job and wait on result will retry as specified
fn (mut job Job) execute() !
execute the job, start process, process will not be closed . important you need to close the process later by job.close()! otherwise we get zombie processes
fn (mut job Job) wait() !
wait till the job finishes or goes in error
fn (mut job Job) process() !
process (read std.err and std.out of process)
fn (mut job Job) close() !
will wait & close
struct JobError {
Error
pub mut:
job Job
error_type ErrorType
}
struct PingArgs {
pub mut:
address string @[required]
count u8 = 1 // the ping is successful if it got count amount of replies from the other side
timeout u16 = 1 // the time in which the other side should respond in seconds
retry u8
}
struct ProcessInfo {
pub mut:
cpu_perc f32
mem_perc f32
cmd string
pid int
ppid int // parentpid
// resident memory
rss int
}
fn (mut p ProcessInfo) str() string
struct ProcessKillArgs {
pub mut:
name string
pid int
}
struct ProcessMap {
pub mut:
processes []ProcessInfo
lastscan time.Time
state PMState
pids []int
}
struct ProfilePathAddArgs {
pub mut:
path string @[required]
todelete string // see which one to remove
}
struct TcpPortTestArgs {
pub mut:
address string @[required] // 192.168.8.8
port int = 22
timeout u16 = 2000 // total time in milliseconds to keep on trying
}
struct UserArgs {
pub mut:
name string @[required]
}
-
````

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +0,0 @@
generate specs for /Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions
use mcp
get the output of it un actions/specs.v
then use these specs.v
to generate play command instructions see @3_heroscript_vlang.md
this play command gets heroscript in and will then call the methods for actions as are ONLY in @lib/circles/actions/db
so the play only calls the methods in @lib/circles/actions/db
# put the play commands in
/Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions/play
do one file in the module per action
each method is an action
put them all on one Struct called Player
in this Player we have a method per action
Player has a property called actor: which is the name of the actor as is used in the heroscript
Player has also a output called return format which is enum for heroscript or json
input of the method - action is a params object
on player there is a method play which takes the text as input or playbook
if text then playbook is created
then we walk over all actions
all the ones starting with actions in this case are given to the right method

View File

@@ -1 +0,0 @@
../lib/data/encoder/readme.md

View File

@@ -0,0 +1,51 @@
# Cost Module Documentation
This module provides functionalities related to managing various costs within the business model.
## Actions
### `!!bizmodel.cost_define`
Defines a cost item and its associated properties.
**Parameters:**
* `bizname` (string, required): The name of the business model instance to which this cost belongs.
* `descr` (string, required): Description of the cost item. If `name` is not provided, it will be derived from this.
* `name` (string, optional): Unique name for the cost item. If not provided, it will be generated from `descr`.
* `cost` (string, required): The cost value. Can be a fixed value (e.g., '1000USD') or a growth rate (e.g., '0:1000,59:2000'). If `indexation` is used, this should not contain a colon. This value is extrapolated.
* `indexation` (percentage, optional, default: '0%'): Annual indexation rate for the cost. Applied over 6 years if specified.
* `costcenter` (string, optional): The costcenter associated with this cost.
* `cost_percent_revenue` (percentage, optional, default: '0%'): Ensures the cost is at least this percentage of the total revenue.
* `extrapolate`: If you want to extrapolate revenue or cogs do extrapolate:1, default is 0.
### `!!bizmodel.costcenter_define`
Defines a cost center.
**Parameters:**
* `bizname` (string, required): The name of the business model instance to which this cost belongs.
* `descr` (string, required): Description of the cost center. If `name` is not provided, it will be derived from this.
* `name` (string, optional): Unique name for the cost center. If not provided, it will be generated from `descr`.
* `department` (string, optional): The department associated with this cost center.
## **Example:**
```js
!!bizmodel.costcenter_define bizname:'test'
descr:'Marketing Cost Center'
name:'marketing_cc'
department:'marketing'
!!bizmodel.cost_define bizname:'test'
descr:'Office Rent'
cost:'5000USD'
indexation:'3%'
costcenter:'marketing_cc'
cost_percent_revenue:'1%'
```

View File

@@ -0,0 +1,35 @@
# Funding Module Documentation
This module provides functionalities related to managing various funding sources within the business model.
## Actions
### `!!bizmodel.funding_define`
Defines a funding entity and its associated properties.
**Parameters:**
* `bizname` (string, required): The name of the business model instance to which this funding belongs.
* `name` (string, required): Identifier for the funding entity.
* `descr` (string, optional): Human-readable description. If not provided, it will be derived from `description`.
* `investment` (string, required): Format `month:amount`, e.g., '0:10000,12:5000'. This value is extrapolated.
* `type` (string, optional, default: 'capital'): The type of funding. Allowed values: 'loan' or 'capital'.
* `extrapolate`: If you want to extrapolate revenue or cogs do extrapolate:1, default is 0.
### `funding_total`
Calculates the total funding.
## **Example:**
```js
!!bizmodel.funding_define bizname:'test' name:'seed_capital'
descr:'Initial Seed Capital Investment'
investment:'0:500000,12:200000'
type:'capital'
!!bizmodel.funding_define bizname:'test' name:'bank_loan'
descr:'Bank Loan for Expansion'
investment:'6:100000,18:50000'
type:'loan'

View File

@@ -0,0 +1,24 @@
create a bizmodel for a startup called threefold
it has 4 departments
- engineering
- operations
- sales
- admin
I need modest engineering 10, 5 people, team nr of people grows 10% per year, with max of 20 people
I need operational team of 2 people and 4% of revenue
I am selling services on a cloud, it starts at 10k USD a month after 10 months, then growing to 1 million a month after 3 years, then 5% up per year
we have 3 offices
we have 5m funding day 1
travelcost is 3% of revenue
create me the full heroscript which gives me this biz model
create bizmodel.heroscript in ~/code/github/freeflowuniverse/herolib/examples/biztools/generated_ai
as well as a do.vsh file which executes the heroscript and does a pprint, in do.vsh , call play with heroscript_path arg

View File

@@ -0,0 +1,69 @@
# HR Module Documentation
This module provides functionalities related to Human Resources within the business model.
## Actions
All actions in the `bizmodel` module accept a `bizname` parameter (string, required) which specifies the business model instance to which the action applies.
### `bizmodel.employee_define`
Defines an employee and their associated costs within the business model.
**Parameters:**
* `bizname` (string, required): The name of the business model instance to which this cost belongs.
* `descr` (string, required): Description of the employee (e.g., 'Junior Engineer'). If `name` is not provided, it will be derived from this.
* `name` (string, optional): Unique name for the employee. If not provided, it will be generated from `descr`.
* `cost` (string, required): The cost associated with the employee. Can be a fixed value (e.g., '4000USD') or a growth rate (e.g., '1:5,60:30'). If `indexation` is used, this should not contain a colon.
* `nrpeople` (string, optional, default: '1'): The number of people for this employee definition. Can be a fixed number or a growth rate (e.g., '1:5,60:30').
* `indexation` (percentage, optional, default: '0%'): Annual indexation rate for the cost. Applied over 6 years if specified.
* `department` (string, optional): The department the employee belongs to.
* `cost_percent_revenue` (percentage, optional, default: '0%'): Ensures the employee cost is at least this percentage of the total revenue.
* `costcenter` (string, optional, default: 'default_costcenter'): The cost center for the employee.
* `page` (string, optional): A reference to a page or document related to this employee.
* `fulltime` (percentage, optional, default: '100%'): The full-time percentage of the employee.
### `bizmodel.department_define`
Defines a department within the business model.
**Parameters:**
* `bizname` (string, required): The name of the business model instance to which this cost belongs.
* `name` (string, required): Unique name for the department.
* `descr` (string, optional): Description of the department. If not provided, `description` will be used.
* `description` (string, optional): Description of the department. Used if `descr` is not provided.
* `title` (string, optional): A title for the department.
* `page` (string, optional): A reference to a page or document related to this department.
## **Example:**
```js
!!bizmodel.department_define bizname:'test'
name:'engineering'
descr:'Software Development Department'
title:'Engineering Division'
//optional, if set overrules the hr_params
//avg_monthly_cost:'6000USD' avg_indexation:'5%'
!!bizmodel.employee_define bizname:'test'
name:'ourclo'
descr:'CLO'
cost:'10000EUR'
indexation:'5%'
!!bizmodel.employee_define bizname:'test'
name:'junior_engineer'
descr:'Junior Engineer'
nrpeople:'1:5,60:30'
cost:'4000USD'
indexation:'5%'
department:'engineering'
cost_percent_revenue:'4%'
```

View File

@@ -0,0 +1,92 @@
# Revenue
```
!!bizmodel.revenue_define bizname:'test' name:'oem1' ...
```
## Params
- bizname, is the name of the biz model we are populating
- name, name of product, project
- descr, description of the revenue line item
- nr_months_recurring: e.g. 60 is 5 years
## discrete revenue/cogs (not per item)
cogs stands for cost of goods
- revenue: one of revenue, can be extrapolated if specified
- cogs: cost of goods, this is the cost of the revenue, can be extrapolated if specified
- cogs_percent: percent of revenue
- cogs_delay: delay in months between cogs and revenue
- extrapolate: if you want to extrapolate revenue or cogs do extrapolate:1, default is 0
### results in
follow rows in sheets
- {name}_ + all the arg names as mentioned above...
- {name}_revenue_total
- {name}_cogs_total
## grouped per items sold
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200, default is 1)
- revenue_item_setup, revenue for 1 item '1000usd'
- revenue_item_setup_delay, delay between sell and recognition of sale in months e.g. 1
- revenue_item_monthly, revenue per month for 1 item
- revenue_item_monthly_delay, how many months before monthly revenue starts
- revenue_item_monthly_perc, how much percent of revenue_item_setup will come back over months e.g. 20%
- cogs_item_setup, cost of good for 1 item at setup
- cogs_item_setup_rev_perc: what is percentage of the revenue which is cogs, e.g. 2%
- cogs_item_monthly, cost of goods for the monthly per 1 item
- cogs_item_monthly_rev_perc: what is percentage of the monthly revenue which is cogs, e.g. 10%
- cogs_item_delay, how many months before cogs starts after sales
### results in
follow rows in sheets
- {name}_ + all the arg names as mentioned above...
- {name}_revenue_item_setup_total
- {name}_revenue_item_monthly_total
- {name}_revenue_item_total
- {name}_cogs_item_total
## to use
### basic example
```v
import freeflowuniverse.herolib.biz.bizmodel
import os
heroscript:="
Next will define an OEM product in month 10, 1 Million EUR, ... cogs is a percent which is 20% at start but goes to 10% after 20 months.
!!bizmodel.revenue_define bizname:'test' name:'oem1'
descr:'OEM Deals'
revenue:'10:1000000EUR,15:3333,20:1200000'
cogs_percent: '1:20%,20:10%'
This time we have the cogs defined in fixed manner, the default currency is USD doesn't have to be mentioned.
!!bizmodel.revenue_define bizname:'test' name:'oem2'
descr:'OEM Deals'
revenue:'10:1000000EUR,15:3333,20:1200000'
cogs: '10:100000,15:1000,20:120000'
"
bizmodel.play(heroscript:heroscript)!
mut bm:=bizmodel.get("test")!
bm.sheet.pprint()!
```

View File

@@ -0,0 +1,38 @@
//need to define some revenue because otherwise can't see how HR relates to it
!!bizmodel.revenue_define bizname:'test' name:'oem1' extrapolate:1
descr:'OEM Deals' revenue:'0:1000000,60:10000000'
cogs_percent: '0:20%'
!!bizmodel.department_define bizname:'test' name:'marketing'
descr:'Marketing Department'
!!bizmodel.department_define bizname:'test' name:'engineering'
descr:'Engineering Department'
!!bizmodel.costcenter_define bizname:'test' name:'marketing_cc'
descr:'Marketing Cost Center'
department:'marketing'
!!bizmodel.cost_define bizname:'test' name:'office_rent'
descr:'Office Rent'
cost:'8000USD'
indexation:'3%'
costcenter:'marketing_cc'
cost_percent_revenue:'0.5%'
!!bizmodel.cost_define bizname:'test' name:'travel'
descr:'Office Rent'
cost:'2:5000USD' //start month 3
costcenter:'marketing_cc'
!!bizmodel.cost_define bizname:'test' name:'triptomoon'
descr:'Office Rent'
cost:'10:500000USD' extrapolate:0 //this means we do a one off cost in this case month 11
costcenter:'marketing_cc'
// !!bizmodel.cost_define bizname:'test' name:'software_licenses'
// descr:'Annual Software Licenses'
// cost:'0:10000 10:EUR:20kCHF,12:5000USD'
// department:'engineering'

View File

@@ -1,15 +0,0 @@
for @lib/circles/mcc
generate openapi 3.1 spec
do it as one file called openapi.yaml and put in the dir as mentioned above
based on the models and db implementation
implement well chosen examples in the openapi spec
note: in OpenAPI 3.1.0, the example property is deprecated in favor of examples
do this for the models & methods as defined below
do it also for the custom and generic methods, don't forget any

View File

@@ -1,197 +0,0 @@
in @lib/circles/mcc
generate openapi 3.1 spec
based on the models and db implementation
implement well chosen examples in the openapi spec
note: in OpenAPI 3.1.0, the example property is deprecated in favor of examples.
do this for the models & methods as defined below
do it for custom and generic methods, don't forget any
```v
// CalendarEvent represents a calendar event with all its properties
pub struct CalendarEvent {
pub mut:
id u32 // Unique identifier
title string // Event title
description string // Event details
location string // Event location
start_time ourtime.OurTime
end_time ourtime.OurTime // End time
all_day bool // True if it's an all-day event
recurrence string // RFC 5545 Recurrence Rule (e.g., "FREQ=DAILY;COUNT=10")
attendees []string // List of emails or user IDs
organizer string // Organizer email
status string // "CONFIRMED", "CANCELLED", "TENTATIVE"
caldav_uid string // CalDAV UID for syncing
sync_token string // Sync token for tracking changes
etag string // ETag for caching
color string // User-friendly color categorization
}
// Email represents an email message with all its metadata and content
pub struct Email {
pub mut:
// Database ID
id u32 // Database ID (assigned by DBHandler)
// Content fields
uid u32 // Unique identifier of the message (in the circle)
seq_num u32 // IMAP sequence number (in the mailbox)
mailbox string // The mailbox this email belongs to
message string // The email body content
attachments []Attachment // Any file attachments
// IMAP specific fields
flags []string // IMAP flags like \Seen, \Deleted, etc.
internal_date i64 // Unix timestamp when the email was received
size u32 // Size of the message in bytes
envelope ?Envelope // IMAP envelope information (contains From, To, Subject, etc.)
}
// Attachment represents an email attachment
pub struct Attachment {
pub mut:
filename string
content_type string
data string // Base64 encoded binary data
}
// Envelope represents an IMAP envelope structure
pub struct Envelope {
pub mut:
date i64
subject string
from []string
sender []string
reply_to []string
to []string
cc []string
bcc []string
in_reply_to string
message_id string
}
```
methods
```v
pub fn (mut m MailDB) new() Email {
}
// set adds or updates an email
pub fn (mut m MailDB) set(email Email) !Email {
}
// get retrieves an email by its ID
pub fn (mut m MailDB) get(id u32) !Email {
}
// list returns all email IDs
pub fn (mut m MailDB) list() ![]u32 {
}
pub fn (mut m MailDB) getall() ![]Email {
}
// delete removes an email by its ID
pub fn (mut m MailDB) delete(id u32) ! {
}
//////////////////CUSTOM METHODS//////////////////////////////////
// get_by_uid retrieves an email by its UID
pub fn (mut m MailDB) get_by_uid(uid u32) !Email {
}
// get_by_mailbox retrieves all emails in a specific mailbox
pub fn (mut m MailDB) get_by_mailbox(mailbox string) ![]Email {
}
// delete_by_uid removes an email by its UID
pub fn (mut m MailDB) delete_by_uid(uid u32) ! {
}
// delete_by_mailbox removes all emails in a specific mailbox
pub fn (mut m MailDB) delete_by_mailbox(mailbox string) ! {
}
// update_flags updates the flags of an email
pub fn (mut m MailDB) update_flags(uid u32, flags []string) !Email {
}
// search_by_subject searches for emails with a specific subject substring
pub fn (mut m MailDB) search_by_subject(subject string) ![]Email {
}
// search_by_address searches for emails with a specific email address in from, to, cc, or bcc fields
pub fn (mut m MailDB) search_by_address(address string) ![]Email {
}
pub fn (mut c CalendarDB) new() CalendarEvent {
CalendarEvent {}
}
// set adds or updates a calendar event
pub fn (mut c CalendarDB) set(event CalendarEvent) CalendarEvent {
CalendarEvent {}
}
// get retrieves a calendar event by its ID
pub fn (mut c CalendarDB) get(id u32) CalendarEvent {
CalendarEvent {}
}
// list returns all calendar event IDs
pub fn (mut c CalendarDB) list() []u32 {
[]
}
pub fn (mut c CalendarDB) getall() []CalendarEvent {
[]
}
// delete removes a calendar event by its ID
pub fn (mut c CalendarDB) delete(id u32) {
}
//////////////////CUSTOM METHODS//////////////////////////////////
// get_by_caldav_uid retrieves a calendar event by its CalDAV UID
pub fn (mut c CalendarDB) get_by_caldav_uid(caldav_uid String) CalendarEvent {
CalendarEvent {}
}
// get_events_by_date retrieves all events that occur on a specific date
pub fn (mut c CalendarDB) get_events_by_date(date String) []CalendarEvent {
[]
}
// get_events_by_organizer retrieves all events organized by a specific person
pub fn (mut c CalendarDB) get_events_by_organizer(organizer String) []CalendarEvent {
[]
}
// get_events_by_attendee retrieves all events that a specific person is attending
pub fn (mut c CalendarDB) get_events_by_attendee(attendee String) []CalendarEvent {
[]
}
// search_events_by_title searches for events with a specific title substring
pub fn (mut c CalendarDB) search_events_by_title(title String) []CalendarEvent {
[]
}
// update_status updates the status of an event
pub fn (mut c CalendarDB) update_status(id u32, status String) CalendarEvent {
CalendarEvent {}
}
// delete_by_caldav_uid removes an event by its CalDAV UID
pub fn (mut c CalendarDB) delete_by_caldav_uid(caldav_uid String) {
}
```

View File

@@ -1,26 +0,0 @@
create a module vfs_mail in @lib/vfs
check the interface as defined in @lib/vfs/interface.v and @metadata.v
see example how a vfs is made in @lib/vfs/vfs_local
create the vfs to represent mail objects in @lib/circles/dbs/core/mail_db.v
mailbox propery on the Email object defines the path in the vfs
this mailbox property can be e.g. Draft/something/somethingelse
in that dir show a subdir /id:
- which show the Email as a json underneith the ${email.id}.json
in that dir show subdir /subject:
- which show the Email as a json underneith the name_fix(${email.envelope.subject}.json
so basically we have 2 representations of the same mail in the vfs, both have the. json as content of the file

View File

@@ -1 +0,0 @@
../lib/data/currency/readme.md

View File

@@ -1,340 +0,0 @@
module datatypes
# datatypes
This module provides implementations of less frequently used, but still common data types.
V's `builtin` module is imported implicitly, and has implementations for arrays, maps and strings. These are good for many applications, but there are a plethora of other useful data structures/containers, like linked lists, priority queues, trees, etc, that allow for algorithms with different time complexities, which may be more suitable for your specific application.
It is implemented using generics, that you have to specialise for the type of your actual elements. For example:
```v
import datatypes
mut stack := datatypes.Stack[int]{}
stack.push(1)
println(stack)
```
## Currently Implemented Datatypes:
- [x] Linked list
- [x] Doubly linked list
- [x] Stack (LIFO)
- [x] Queue (FIFO)
- [x] Min heap (priority queue)
- [x] Set
- [x] Quadtree
- [x] Bloom filter
- [ ] ...
fn new_bloom_filter[T](hash_func fn (T) u32, table_size int, num_functions int) !&BloomFilter[T]
new_bloom_filter creates a new bloom_filter. `table_size` should be greater than 0, and `num_functions` should be 1~16.
fn new_bloom_filter_fast[T](hash_func fn (T) u32) &BloomFilter[T]
new_bloom_filter_fast creates a new bloom_filter. `table_size` is 16384, and `num_functions` is 4.
fn new_ringbuffer[T](s int) RingBuffer[T]
new_ringbuffer creates an empty ring buffer of size `s`.
fn (mut bst BSTree[T]) insert(value T) bool
insert give the possibility to insert an element in the BST.
fn (bst &BSTree[T]) contains(value T) bool
contains checks if an element with a given `value` is inside the BST.
fn (mut bst BSTree[T]) remove(value T) bool
remove removes an element with `value` from the BST.
fn (bst &BSTree[T]) is_empty() bool
is_empty checks if the BST is empty
fn (bst &BSTree[T]) in_order_traversal() []T
in_order_traversal traverses the BST in order, and returns the result as an array.
fn (bst &BSTree[T]) post_order_traversal() []T
post_order_traversal traverses the BST in post order, and returns the result in an array.
fn (bst &BSTree[T]) pre_order_traversal() []T
pre_order_traversal traverses the BST in pre order, and returns the result as an array.
fn (bst &BSTree[T]) to_left(value T) !T
to_left returns the value of the node to the left of the node with `value` specified if it exists, otherwise the a false value is returned.
An example of usage can be the following one
```v
left_value, exist := bst.to_left(10)
```
fn (bst &BSTree[T]) to_right(value T) !T
to_right return the value of the element to the right of the node with `value` specified, if exist otherwise, the boolean value is false An example of usage can be the following one
```v
left_value, exist := bst.to_right(10)
```
fn (bst &BSTree[T]) max() !T
max return the max element inside the BST. Time complexity O(N) if the BST is not balanced
fn (bst &BSTree[T]) min() !T
min return the minimum element in the BST. Time complexity O(N) if the BST is not balanced.
fn (mut b BloomFilter[T]) add(element T)
adds the element to bloom filter.
fn (b &BloomFilter[T]) exists(element T) bool
checks the element is exists.
fn (l &BloomFilter[T]) @union(r &BloomFilter[T]) !&BloomFilter[T]
@union returns the union of the two bloom filters.
fn (l &BloomFilter[T]) intersection(r &BloomFilter[T]) !&BloomFilter[T]
intersection returns the intersection of bloom filters.
fn (list DoublyLinkedList[T]) is_empty() bool
is_empty checks if the linked list is empty
fn (list DoublyLinkedList[T]) len() int
len returns the length of the linked list
fn (list DoublyLinkedList[T]) first() !T
first returns the first element of the linked list
fn (list DoublyLinkedList[T]) last() !T
last returns the last element of the linked list
fn (mut list DoublyLinkedList[T]) push_back(item T)
push_back adds an element to the end of the linked list
fn (mut list DoublyLinkedList[T]) push_front(item T)
push_front adds an element to the beginning of the linked list
fn (mut list DoublyLinkedList[T]) push_many(elements []T, direction Direction)
push_many adds array of elements to the beginning of the linked list
fn (mut list DoublyLinkedList[T]) pop_back() !T
pop_back removes the last element of the linked list
fn (mut list DoublyLinkedList[T]) pop_front() !T
pop_front removes the last element of the linked list
fn (mut list DoublyLinkedList[T]) insert(idx int, item T) !
insert adds an element to the linked list at the given index
fn (list &DoublyLinkedList[T]) index(item T) !int
index searches the linked list for item and returns the forward index or none if not found.
fn (mut list DoublyLinkedList[T]) delete(idx int)
delete removes index idx from the linked list and is safe to call for any idx.
fn (list DoublyLinkedList[T]) str() string
str returns a string representation of the linked list
fn (list DoublyLinkedList[T]) array() []T
array returns a array representation of the linked list
fn (mut list DoublyLinkedList[T]) next() ?T
next implements the iter interface to use DoublyLinkedList with V's `for x in list {` loop syntax.
fn (mut list DoublyLinkedList[T]) iterator() DoublyListIter[T]
iterator returns a new iterator instance for the `list`.
fn (mut list DoublyLinkedList[T]) back_iterator() DoublyListIterBack[T]
back_iterator returns a new backwards iterator instance for the `list`.
fn (mut iter DoublyListIterBack[T]) next() ?T
next returns *the previous* element of the list, or `none` when the start of the list is reached. It is called by V's `for x in iter{` on each iteration.
fn (mut iter DoublyListIter[T]) next() ?T
next returns *the next* element of the list, or `none` when the end of the list is reached. It is called by V's `for x in iter{` on each iteration.
fn (list LinkedList[T]) is_empty() bool
is_empty checks if the linked list is empty
fn (list LinkedList[T]) len() int
len returns the length of the linked list
fn (list LinkedList[T]) first() !T
first returns the first element of the linked list
fn (list LinkedList[T]) last() !T
last returns the last element of the linked list
fn (list LinkedList[T]) index(idx int) !T
index returns the element at the given index of the linked list
fn (mut list LinkedList[T]) push(item T)
push adds an element to the end of the linked list
fn (mut list LinkedList[T]) push_many(elements []T)
push adds an array of elements to the end of the linked list
fn (mut list LinkedList[T]) pop() !T
pop removes the last element of the linked list
fn (mut list LinkedList[T]) shift() !T
shift removes the first element of the linked list
fn (mut list LinkedList[T]) insert(idx int, item T) !
insert adds an element to the linked list at the given index
fn (mut list LinkedList[T]) prepend(item T)
prepend adds an element to the beginning of the linked list (equivalent to insert(0, item))
fn (list LinkedList[T]) str() string
str returns a string representation of the linked list
fn (list LinkedList[T]) array() []T
array returns a array representation of the linked list
fn (mut list LinkedList[T]) next() ?T
next implements the iteration interface to use LinkedList with V's `for` loop syntax.
fn (mut list LinkedList[T]) iterator() ListIter[T]
iterator returns a new iterator instance for the `list`.
fn (mut iter ListIter[T]) next() ?T
next returns the next element of the list, or `none` when the end of the list is reached. It is called by V's `for x in iter{` on each iteration.
fn (mut heap MinHeap[T]) insert(item T)
insert adds an element to the heap.
fn (mut heap MinHeap[T]) insert_many(elements []T)
insert array of elements to the heap.
fn (mut heap MinHeap[T]) pop() !T
pop removes the top-most element from the heap.
fn (heap MinHeap[T]) peek() !T
peek gets the top-most element from the heap without removing it.
fn (heap MinHeap[T]) len() int
len returns the number of elements in the heap.
fn (queue Queue[T]) is_empty() bool
is_empty checks if the queue is empty
fn (queue Queue[T]) len() int
len returns the length of the queue
fn (queue Queue[T]) peek() !T
peek returns the head of the queue (first element added)
fn (queue Queue[T]) last() !T
last returns the tail of the queue (last element added)
fn (queue Queue[T]) index(idx int) !T
index returns the element at the given index of the queue
fn (mut queue Queue[T]) push(item T)
push adds an element to the tail of the queue
fn (mut queue Queue[T]) pop() !T
pop removes the element at the head of the queue and returns it
fn (queue Queue[T]) str() string
str returns a string representation of the queue
fn (queue Queue[T]) array() []T
array returns a array representation of the queue
fn (mut rb RingBuffer[T]) push(element T) !
push adds an element to the ring buffer.
fn (mut rb RingBuffer[T]) pop() !T
pop returns the oldest element in the buffer.
fn (mut rb RingBuffer[T]) push_many(elements []T) !
push_many pushes an array to the buffer.
fn (mut rb RingBuffer[T]) pop_many(n u64) ![]T
pop_many returns `n` elements of the buffer starting with the oldest one.
fn (rb RingBuffer[T]) is_empty() bool
is_empty returns `true` if the ring buffer is empty, `false` otherwise.
fn (rb RingBuffer[T]) is_full() bool
is_full returns `true` if the ring buffer is full, `false` otherwise.
fn (rb RingBuffer[T]) capacity() int
capacity returns the capacity of the ring buffer.
fn (mut rb RingBuffer[T]) clear()
clear empties the ring buffer and all pushed elements.
fn (rb RingBuffer[T]) occupied() int
occupied returns the occupied capacity of the buffer.
fn (rb RingBuffer[T]) remaining() int
remaining returns the remaining capacity of the buffer.
fn (set Set[T]) exists(element T) bool
checks the element is exists.
fn (mut set Set[T]) add(element T)
adds the element to set, if it is not present already.
fn (mut set Set[T]) remove(element T)
removes the element from set.
fn (set Set[T]) pick() !T
pick returns an arbitrary element of set, if set is not empty.
fn (mut set Set[T]) rest() ![]T
rest returns the set consisting of all elements except for the arbitrary element.
fn (mut set Set[T]) pop() !T
pop returns an arbitrary element and deleting it from set.
fn (mut set Set[T]) clear()
delete all elements of set.
fn (l Set[T]) == (r Set[T]) bool
== checks whether the two given sets are equal (i.e. contain all and only the same elements).
fn (set Set[T]) is_empty() bool
is_empty checks whether the set is empty or not.
fn (set Set[T]) size() int
size returns the number of elements in the set.
fn (set Set[T]) copy() Set[T]
copy returns a copy of all the elements in the set.
fn (mut set Set[T]) add_all(elements []T)
add_all adds the whole `elements` array to the set
fn (l Set[T]) @union(r Set[T]) Set[T]
@union returns the union of the two sets.
fn (l Set[T]) intersection(r Set[T]) Set[T]
intersection returns the intersection of sets.
fn (l Set[T]) - (r Set[T]) Set[T]
- returns the difference of sets.
fn (l Set[T]) subset(r Set[T]) bool
subset returns true if the set `r` is a subset of the set `l`.
fn (stack Stack[T]) is_empty() bool
is_empty checks if the stack is empty
fn (stack Stack[T]) len() int
len returns the length of the stack
fn (stack Stack[T]) peek() !T
peek returns the top of the stack
fn (mut stack Stack[T]) push(item T)
push adds an element to the top of the stack
fn (mut stack Stack[T]) pop() !T
pop removes the element at the top of the stack and returns it
fn (stack Stack[T]) str() string
str returns a string representation of the stack
fn (stack Stack[T]) array() []T
array returns a array representation of the stack
enum Direction {
front
back
}
struct AABB {
pub mut:
x f64
y f64
width f64
height f64
}
struct BSTree[T] {
mut:
root &BSTreeNode[T] = unsafe { 0 }
}
Pure Binary Seach Tree implementation
Pure V implementation of the Binary Search Tree Time complexity of main operation O(log N) Space complexity O(N)
struct DoublyLinkedList[T] {
mut:
head &DoublyListNode[T] = unsafe { 0 }
tail &DoublyListNode[T] = unsafe { 0 }
// Internal iter pointer for allowing safe modification
// of the list while iterating. TODO: use an option
// instead of a pointer to determine it is initialized.
iter &DoublyListIter[T] = unsafe { 0 }
len int
}
DoublyLinkedList[T] represents a generic doubly linked list of elements, each of type T.
struct DoublyListIter[T] {
mut:
node &DoublyListNode[T] = unsafe { 0 }
}
DoublyListIter[T] is an iterator for DoublyLinkedList. It starts from *the start* and moves forwards to *the end* of the list. It can be used with V's `for x in iter {` construct. One list can have multiple independent iterators, pointing to different positions/places in the list. A DoublyListIter iterator instance always traverses the list from *start to finish*.
struct DoublyListIterBack[T] {
mut:
node &DoublyListNode[T] = unsafe { 0 }
}
DoublyListIterBack[T] is an iterator for DoublyLinkedList. It starts from *the end* and moves backwards to *the start* of the list. It can be used with V's `for x in iter {` construct. One list can have multiple independent iterators, pointing to different positions/places in the list. A DoublyListIterBack iterator instance always traverses the list from *finish to start*.
struct LinkedList[T] {
mut:
head &ListNode[T] = unsafe { 0 }
len int
// Internal iter pointer for allowing safe modification
// of the list while iterating. TODO: use an option
// instead of a pointer to determine if it is initialized.
iter &ListIter[T] = unsafe { 0 }
}
struct ListIter[T] {
mut:
node &ListNode[T] = unsafe { 0 }
}
ListIter[T] is an iterator for LinkedList. It can be used with V's `for x in iter {` construct. One list can have multiple independent iterators, pointing to different positions/places in the list. An iterator instance always traverses the list from start to finish.
struct ListNode[T] {
mut:
data T
next &ListNode[T] = unsafe { 0 }
}
struct MinHeap[T] {
mut:
data []T
}
MinHeap is a binary minimum heap data structure.
struct Quadtree {
pub mut:
perimeter AABB
capacity int
depth int
level int
particles []AABB
nodes []Quadtree
}
fn (mut q Quadtree) create(x f64, y f64, width f64, height f64, capacity int, depth int, level int) Quadtree
create returns a new configurable root node for the tree.
fn (mut q Quadtree) insert(p AABB)
insert recursively adds a particle in the correct index of the tree.
fn (mut q Quadtree) retrieve(p AABB) []AABB
retrieve recursively checks if a particle is in a specific index of the tree.
fn (mut q Quadtree) clear()
clear flushes out nodes and particles from the tree.
fn (q Quadtree) get_nodes() []Quadtree
get_nodes recursively returns the subdivisions the tree has.
struct Queue[T] {
mut:
elements LinkedList[T]
}
struct RingBuffer[T] {
mut:
reader int // index of the tail where data is going to be read
writer int // index of the head where data is going to be written
content []T
}
RingBuffer represents a ring buffer also known as a circular buffer.
struct Set[T] {
mut:
elements map[T]u8
}
struct Stack[T] {
mut:
elements []T
}

View File

@@ -1,79 +0,0 @@
## how internally a heroscript gets parsed for params
- example to show how a heroscript gets parsed in action with params
- params are part of action object
```heroscript
example text to parse (heroscript)
id:a1 name6:aaaaa
name:'need to do something 1'
description:
'
## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
name2: test
name3: hi
name10:'this is with space' name11:aaa11
name4: 'aaa'
//somecomment
name5: 'aab'
```
the params are part of the action and are represented as follow for the above:
```vlang
Params{
params: [Param{
key: 'id'
value: 'a1'
}, Param{
key: 'name6'
value: 'aaaaa'
}, Param{
key: 'name'
value: 'need to do something 1'
}, Param{
key: 'description'
value: '## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
}, Param{
key: 'name2'
value: 'test'
}, Param{
key: 'name3'
value: 'hi'
}, Param{
key: 'name10'
value: 'this is with space'
}, Param{
key: 'name11'
value: 'aaa11'
}, Param{
key: 'name4'
value: 'aaa'
}, Param{
key: 'name5'
value: 'aab'
}]
}
```

View File

@@ -1 +0,0 @@
../crystallib/virt/docker/readme.md

View File

@@ -0,0 +1,344 @@
# HeroLib Docusaurus Ebook Manual for AI Prompts
This manual provides a comprehensive guide on how to leverage HeroLib's Docusaurus integration, Doctree, and HeroScript to create and manage technical ebooks, optimized for AI-driven content generation and project management.
## 1. Core Concepts
To effectively create ebooks with HeroLib, it's crucial to understand the interplay of three core components:
* **HeroScript**: A concise scripting language used to define the structure, configuration, and content flow of your Docusaurus site. It acts as the declarative interface for the entire process.
* **Docusaurus**: A popular open-source static site generator. HeroLib uses Docusaurus as the underlying framework to render your ebook content into a navigable website.
* **Doctree**: HeroLib's content management system. Doctree organizes your markdown files into "collections" and "pages," allowing for structured content retrieval and reuse across multiple projects.
## 2. Setting Up a Docusaurus Project with HeroLib
The `docusaurus` module in HeroLib provides the primary interface for managing your ebook projects.
### 2.1. Defining the Docusaurus Factory (`docusaurus.define`)
The `docusaurus.define` HeroScript directive configures the global settings for your Docusaurus build environment. This is typically used once at the beginning of your main HeroScript configuration.
**HeroScript Example:**
```heroscript
!!docusaurus.define
path_build: "/tmp/my_ebook_build"
path_publish: "/tmp/my_ebook_publish"
production: true
update: true
```
**Arguments:**
* `path_build` (string, optional): The local path where the Docusaurus site will be built. Defaults to `~/hero/var/docusaurus/build`.
* `path_publish` (string, optional): The local path where the final Docusaurus site will be published (e.g., for deployment). Defaults to `~/hero/var/docusaurus/publish`.
* `production` (boolean, optional): If `true`, the site will be built for production (optimized). Default is `false`.
* `update` (boolean, optional): If `true`, the Docusaurus template and dependencies will be updated. Default is `false`.
### 2.2. Adding a Docusaurus Site (`docusaurus.add`)
The `docusaurus.add` directive defines an individual Docusaurus site (your ebook). You can specify the source of your documentation content, whether it's a local path or a Git repository.
**HeroScript Example (Local Content):**
```heroscript
!!docusaurus.add
name:"my_local_ebook"
path:"./my_ebook_content" // Path to your local docs directory
open:true // Open in browser after generation
```
**HeroScript Example (Git Repository Content):**
```heroscript
!!docusaurus.add
name:"tfgrid_tech_ebook"
git_url:"https://git.threefold.info/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech"
git_reset:true // Reset Git repository before pulling
git_pull:true // Pull latest changes
git_root:"/tmp/git_clones" // Optional: specify a root directory for git clones
```
**Arguments:**
* `name` (string, optional): A unique name for your Docusaurus site/ebook. Defaults to "main".
* `path` (string, optional): The local file system path to the root of your documentation content (e.g., where your `docs` and `cfg` directories are).
* `git_url` (string, optional): A Git URL to a repository containing your documentation content. HeroLib will clone/pull this repository.
* `git_reset` (boolean, optional): If `true`, the Git repository will be reset to a clean state before pulling. Default is `false`.
* `git_pull` (boolean, optional): If `true`, the Git repository will be pulled to get the latest changes. Default is `false`.
* `git_root` (string, optional): An optional root directory where Git repositories will be cloned.
* `nameshort` (string, optional): A shorter name for the Docusaurus site. Defaults to the value of `name`.
* `path_publish` (string, optional): Overrides the factory's `path_publish` for this specific site.
* `production` (boolean, optional): Overrides the factory's `production` setting for this specific site.
* `watch_changes` (boolean, optional): If `true`, HeroLib will watch for changes in your source `docs` directory and trigger rebuilds. Default is `true`.
* `update` (boolean, optional): If `true`, this specific documentation will be updated. Default is `false`.
* `open` (boolean, optional): If `true`, the Docusaurus site will be opened in your default browser after generation/development server start. Default is `false`.
* `init` (boolean, optional): If `true`, the Docusaurus site will be initialized (e.g., creating missing `docs` directories). Default is `false`.
## 3. Structuring Content with HeroScript and Doctree
The actual content and structure of your ebook are defined using HeroScript directives within your site's configuration files (e.g., in a `cfg` directory within your `path` or `git_url` source).
### 3.1. Site Configuration (`site.config`, `site.config_meta`)
These directives define the fundamental properties and metadata of your Docusaurus site.
**HeroScript Example:**
```heroscript
!!site.config
name:"my_awesome_ebook"
title:"My Awesome Ebook Title"
tagline:"A comprehensive guide to everything."
url:"https://my-ebook.example.com"
url_home:"docs/"
base_url:"/my-ebook/"
favicon:"img/favicon.png"
copyright:"© 2024 My Organization"
!!site.config_meta
description:"This ebook covers advanced topics in AI and software engineering."
image:"https://my-ebook.example.com/img/social_share.png"
title:"Advanced AI & Software Engineering Ebook"
keywords:"AI, software, engineering, manual, guide"
```
**Arguments:**
* **`site.config`**:
* `name` (string, required): Unique identifier for the site.
* `title` (string, optional): Main title of the site. Defaults to "My Documentation Site".
* `description` (string, optional): General site description.
* `tagline` (string, optional): Short tagline for the site.
* `favicon` (string, optional): Path to the favicon. Defaults to "img/favicon.png".
* `image` (string, optional): General site image (e.g., for social media previews). Defaults to "img/tf_graph.png".
* `copyright` (string, optional): Copyright notice. Defaults to "© [Current Year] Example Organization".
* `url` (string, optional): The main URL where the site will be hosted.
* `base_url` (string, optional): The base URL for Docusaurus (e.g., `/` or `/my-ebook/`).
* `url_home` (string, optional): The path to the home page relative to `base_url`.
* **`site.config_meta`**: Overrides for specific SEO metadata.
* `title` (string, optional): Specific title for SEO (e.g., `<meta property="og:title">`).
* `image` (string, optional): Specific image for SEO (e.g., `<meta property="og:image">`).
* `description` (string, optional): Specific description for SEO.
* `keywords` (string, optional): Comma-separated keywords for SEO.
### 3.2. Navigation Bar (`site.navbar`, `site.navbar_item`)
Define the main navigation menu of your Docusaurus site.
**HeroScript Example:**
```heroscript
!!site.navbar
title:"Ebook Navigation"
logo_alt:"Ebook Logo"
logo_src:"img/logo.svg"
logo_src_dark:"img/logo_dark.svg"
!!site.navbar_item
label:"Introduction"
to:"/docs/intro" // Internal Docusaurus path
position:"left"
!!site.navbar_item
label:"External Link"
href:"https://example.com/external" // External URL
position:"right"
```
**Arguments:**
* **`site.navbar`**:
* `title` (string, optional): Title displayed in the navbar. Defaults to `site.config.title`.
* `logo_alt` (string, optional): Alt text for the logo.
* `logo_src` (string, optional): Path to the light mode logo.
* `logo_src_dark` (string, optional): Path to the dark mode logo.
* **`site.navbar_item`**:
* `label` (string, required): Text displayed for the menu item.
* `href` (string, optional): External URL for the link.
* `to` (string, optional): Internal Docusaurus path (e.g., `/docs/my-page`).
* `position` (string, optional): "left" or "right" for placement in the navbar. Defaults to "right".
### 3.3. Footer (`site.footer`, `site.footer_item`)
Configure the footer section of your Docusaurus site.
**HeroScript Example:**
```heroscript
!!site.footer
style:"dark" // "dark" or "light"
!!site.footer_item
title:"Resources" // Grouping title for footer links
label:"API Documentation"
href:"https://api.example.com/docs"
!!site.footer_item
title:"Community"
label:"GitHub"
href:"https://github.com/my-org"
```
**Arguments:**
* **`site.footer`**:
* `style` (string, optional): "dark" or "light" style for the footer. Defaults to "dark".
* **`site.footer_item`**:
* `title` (string, required): The title under which this item will be grouped in the footer.
* `label` (string, required): Text displayed for the footer link.
* `href` (string, optional): External URL for the link.
* `to` (string, optional): Internal Docusaurus path.
### 3.4. Build Destinations (`site.build_dest`, `site.build_dest_dev`)
Specify where the built Docusaurus site should be deployed. This typically involves an SSH connection defined elsewhere (e.g., `!!site.ssh_connection`).
**HeroScript Example:**
```heroscript
!!site.build_dest
ssh_name:"production_server" // Name of a pre-defined SSH connection
path:"/var/www/my-ebook" // Remote path on the server
!!site.build_dest_dev
ssh_name:"dev_server"
path:"/tmp/dev-ebook"
```
**Arguments:**
* `ssh_name` (string, required): The name of the SSH connection to use for deployment.
* `path` (string, required): The destination path on the remote server.
### 3.5. Importing External Content (`site.import`)
This powerful feature allows you to pull markdown content and assets from other Git repositories directly into your Docusaurus site's `docs` directory, with optional text replacement. This is ideal for integrating shared documentation or specifications.
**HeroScript Example:**
```heroscript
!!site.import
url:'https://git.threefold.info/tfgrid/docs_tfgrid4/src/branch/main/collections/cloud_reinvented'
dest:'cloud_reinvented' // Destination subdirectory within your Docusaurus docs folder
replace:'NAME:MyName, URGENCY:red' // Optional: comma-separated key:value pairs for text replacement
```
**Arguments:**
* `url` (string, required): The Git URL of the repository or specific path within a repository to import.
* `dest` (string, required): The subdirectory within your Docusaurus `docs` folder where the imported content will be placed.
* `replace` (string, optional): A comma-separated string of `KEY:VALUE` pairs. During import, all occurrences of `${KEY}` in the imported content will be replaced with `VALUE`.
### 3.6. Defining Pages and Categories (`site.page_category`, `site.page`)
This is where you define the actual content pages and how they are organized into categories within your Docusaurus sidebar.
**HeroScript Example:**
```heroscript
// Define a category
!!site.page_category path:'introduction' label:"Introduction to Ebook" position:10
// Define a page within that category, linking to Doctree content
!!site.page path:'introduction' src:"my_doctree_collection:chapter_1_overview"
title:"Chapter 1: Overview"
description:"A brief introduction to the ebook's content."
position:1 // Order within the category
hide_title:true // Hide the title on the page itself
```
**Arguments:**
* **`site.page_category`**:
* `path` (string, required): The path to the category directory within your Docusaurus `docs` folder (e.g., `introduction` will create `docs/introduction/_category_.json`).
* `label` (string, required): The display name for the category in the sidebar.
* `position` (int, optional): The order of the category in the sidebar.
* `sitename` (string, optional): If you have multiple Docusaurus sites defined, specify which site this category belongs to. Defaults to the current site's name.
* **`site.page`**:
* `src` (string, required): **Crucial for Doctree integration.** This specifies the source of the page content in the format `collection_name:page_name`. HeroLib will fetch the markdown content from the specified Doctree collection and page.
* `path` (string, required): The relative path and filename for the generated markdown file within your Docusaurus `docs` folder (e.g., `introduction/chapter_1.md`). If only a directory is provided (e.g., `introduction/`), the `page_name` from `src` will be used as the filename.
* `title` (string, optional): The title of the page. If not provided, HeroLib will attempt to extract it from the markdown content or use the `page_name`.
* `description` (string, optional): A short description for the page, used in frontmatter.
* `position` (int, optional): The order of the page within its category.
* `hide_title` (boolean, optional): If `true`, the title will not be displayed on the page itself.
* `draft` (boolean, optional): If `true`, the page will be marked as a draft and not included in production builds.
* `title_nr` (int, optional): If set, HeroLib will re-number the markdown headings (e.g., `title_nr:3` will make `# Heading` become `### Heading`). Useful for consistent heading levels across imported content.
### 3.7. Doctree Integration Details
The `site.page` directive's `src` parameter (`collection_name:page_name`) is the bridge to your Doctree content.
**How Doctree Works:**
1. **Collections**: Doctree organizes markdown files into logical groups called "collections." A collection is typically a directory containing markdown files and an empty `.collection` file.
2. **Scanning**: You define which collections Doctree should scan using `!!doctree.scan` in a HeroScript file (e.g., `doctree.heroscript`).
**Example `doctree.heroscript`:**
```heroscript
!!doctree.scan git_url:"https://git.threefold.info/tfgrid/docs_tfgrid4/src/branch/main/collections"
```
This will pull the `collections` directory from the specified Git URL and make its contents available to Doctree.
3. **Page Retrieval**: When `site.page` references `src:"my_collection:my_page"`, HeroLib's `doctreeclient` fetches the content of `my_page.md` from the `my_collection` collection that Doctree has scanned.
## 4. Building and Developing Your Ebook
Once your HeroScript configuration is set up, HeroLib provides commands to build and serve your Docusaurus ebook.
### 4.1. Generating Site Files (`site.generate()`)
The `site.generate()` function (called internally by `build`, `dev`, etc.) performs the core file generation:
* Copies Docusaurus template files.
* Copies your site's `src` and `static` assets.
* Generates Docusaurus configuration JSON files (`main.json`, `navbar.json`, `footer.json`) from your HeroScript `site.config`, `site.navbar`, and `site.footer` directives.
* Copies your source `docs` directory.
* Processes `site.page` and `site.page_category` directives using the `sitegen` module to create the final markdown files and `_category_.json` files in the Docusaurus `docs` directory, fetching content from Doctree.
* Handles `site.import` directives, pulling external content and performing replacements.
### 4.2. Local Development
HeroLib integrates with Docusaurus's development server for live preview.
**HeroScript Example:**
can be stored as example_docusaurus.vsh and then used to generate and develop an ebook
```v
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.web.docusaurus
import os
const cfgpath = os.dir(@FILE)
docusaurus.new(
heroscript: '
// !!docusaurus.define
// path_build: "/tmp/docusaurus_build"
// path_publish: "/tmp/docusaurus_publish"
!!docusaurus.add name:"tfgrid_docs"
path:"${cfgpath}"
!!docusaurus.dev
'
)!
```
the following script suggest to call it do.vsh and put in directory of where the ebook is
```v
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.web.docusaurus
const cfgpath = os.dir(@FILE) + '/cfg'
docusaurus.new(heroscript_path:cfgpath)!
```
by just called do.vsh we can execute on the ebook

View File

@@ -1,14 +0,0 @@
## Environment Variables
```v
import freeflowuniverse.herolib.osal
// Get environment variable
value := osal.env_get('PATH')!
// Set environment variable
osal.env_set('MY_VAR', 'value')!
// Check if environment variable exists
exists := osal.env_exists('MY_VAR')
```

View File

@@ -1 +0,0 @@
../lib/develop/gittools/README.md

View File

@@ -0,0 +1,141 @@
# Pathlib Module: Advanced Listing and Filtering
The `pathlib` module provides powerful capabilities for listing and filtering files and directories, especially through its `list` method. This document explains how to leverage advanced features like regular expressions and various filtering options.
## Advanced File Listing with `path.list()`
The `path.list()` method allows you to retrieve a `PathList` object containing `Path` objects that match specified criteria.
### `ListArgs` Parameters
The `list` method accepts a `ListArgs` struct to control its behavior:
```v
pub struct ListArgs {
pub mut:
regex []string // A slice of regular expressions to filter files.
recursive bool = true // Whether to list files recursively (default true).
ignore_default bool = true // Whether to ignore files starting with . and _ (default true).
include_links bool // Whether to include symbolic links in the list.
dirs_only bool // Whether to include only directories in the list.
files_only bool // Whether to include only files in the list.
}
```
### Usage Examples
Here are examples demonstrating how to use these advanced filtering options:
#### 1. Listing Files by Regex Pattern
You can use regular expressions to filter files based on their names or extensions. The `regex` parameter accepts a slice of strings, where each string is a regex pattern.
```v
import freeflowuniverse.herolib.core.pathlib
// Get a directory path
mut dir := pathlib.get('/some/directory')!
// List only Vlang files (ending with .v)
mut vlang_files := dir.list(
regex: [r'.*\.v$']
)!
// List only image files (png, jpg, svg, jpeg)
mut image_files := dir.list(
regex: [r'.*\.png$', r'.*\.jpg$', r'.*\.svg$', r'.*\.jpeg$']
)!
// List files containing "test" in their name (case-insensitive)
mut test_files := dir.list(
regex: [r'(?i).*test.*'] // (?i) makes the regex case-insensitive
)!
for path_obj in vlang_files.paths {
println(path_obj.path)
}
```
#### 2. Controlling Recursion
By default, `list()` is recursive. You can disable recursion to list only items in the current directory.
```v
import freeflowuniverse.herolib.core.pathlib
mut dir := pathlib.get('/some/directory')!
// List only top-level files and directories (non-recursive)
mut top_level_items := dir.list(
recursive: false
)!
for path_obj in top_level_items.paths {
println(path_obj.path)
}
```
#### 3. Including or Excluding Hidden Files
The `ignore_default` parameter controls whether files and directories starting with `.` or `_` are ignored.
```v
import freeflowuniverse.herolib.core.pathlib
mut dir := pathlib.get('/some/directory')!
// List all files and directories, including hidden ones
mut all_items := dir.list(
ignore_default: false
)!
for path_obj in all_items.paths {
println(path_obj.path)
}
```
#### 4. Including Symbolic Links
By default, symbolic links are ignored when walking the directory structure. Set `include_links` to `true` to include them.
```v
import freeflowuniverse.herolib.core.pathlib
mut dir := pathlib.get('/some/directory')!
// List files and directories, including symbolic links
mut items_with_links := dir.list(
include_links: true
)!
for path_obj in items_with_links.paths {
println(path_obj.path)
}
```
#### 5. Listing Only Directories or Only Files
Use `dirs_only` or `files_only` to restrict the results to only directories or only files.
```v
import freeflowuniverse.herolib.core.pathlib
mut dir := pathlib.get('/some/directory')!
// List only directories (recursive)
mut only_dirs := dir.list(
dirs_only: true
)!
// List only files (non-recursive)
mut only_files := dir.list(
files_only: true,
recursive: false
)!
for path_obj in only_dirs.paths {
println(path_obj.path)
}
```
By combining these parameters, you can create highly specific and powerful file system listing operations tailored to your needs.

View File

@@ -0,0 +1,323 @@
# Builder Module: System Automation and Remote Execution
The `builder` module in Herolib provides a powerful framework for automating system tasks and executing commands on both local and remote machines. It offers a unified interface to manage nodes, execute commands, perform file operations, and maintain persistent state.
## Key Components
- **`BuilderFactory`**: Responsible for creating and managing `Node` instances.
- **`Node`**: Represents a target system (local or remote). It encapsulates system properties (platform, CPU type, environment variables) and provides methods for interaction.
- **`Executor`**: An interface (implemented by `ExecutorLocal` and `ExecutorSSH`) that handles the actual command execution and file operations on the target system.
- **NodeDB (via `Node.done` map)**: A key-value store within each `Node` for persistent state, caching, and tracking execution history.
## Getting Started
### Initializing a Builder and Node
First, import the `builder` module and create a new `BuilderFactory` instance. Then, create a `Node` object, which can represent either the local machine or a remote server.
```v
import freeflowuniverse.herolib.builder
// Create a new builder factory
mut b := builder.new()!
// Create a node for the local machine
mut local_node := b.node_local()!
// Create a node for a remote server via SSH
// Format: "user@ip_address:port" or "ip_address:port" or "ip_address"
mut remote_node := b.node_new(ipaddr: "root@195.192.213.2:2222")!
// Node with custom name and debug enabled
mut named_debug_node := b.node_new(
name: "my_remote_server",
ipaddr: "user@server.example.com:22",
debug: true
)!
```
### `Node` Properties
A `Node` object automatically detects and caches system information. You can access these properties:
```v
// Get platform type (e.g., .osx, .ubuntu, .alpine, .arch)
println(node.platform)
// Get CPU architecture (e.g., .intel, .arm)
println(node.cputype)
// Get hostname
println(node.hostname)
// Get environment variables
env_vars := node.environ_get()!
println(env_vars['HOME'])
// Get node information (category, sshkey, user, ipaddress, port)
info := node.info()
println(info['category'])
```
## Command Execution
The `Node` object provides methods to execute commands on the target system.
### `node.exec(args ExecArgs) !string`
Executes a command and returns its standard output.
```v
import freeflowuniverse.herolib.builder { ExecArgs }
// Execute a command with stdout
result := node.exec(cmd: "ls -la /tmp", stdout: true)!
println(result)
// Execute silently (no stdout)
node.exec(cmd: "mkdir -p /tmp/my_dir", stdout: false)!
```
### `node.exec_silent(cmd string) !string`
Executes a command silently (no stdout) and returns its output.
```v
output := node.exec_silent("echo 'Hello from remote!'")!
println(output)
```
### `node.exec_interactive(cmd string) !`
Executes a command in an interactive shell.
```v
// This will open an interactive shell session
node.exec_interactive("bash")!
```
### `node.exec_cmd(args NodeExecCmd) !string`
A more advanced command execution method that supports caching, periodic execution, and temporary script handling.
```v
import freeflowuniverse.herolib.builder { NodeExecCmd }
// Execute a command, cache its result for 24 hours (48*3600 seconds)
// and provide a description for logging.
result := node.exec_cmd(
cmd: "apt-get update",
period: 48 * 3600,
description: "Update system packages"
)!
println(result)
// Execute a multi-line script
script_output := node.exec_cmd(
cmd: "
echo 'Starting script...'
ls -la /
echo 'Script finished.'
",
name: "my_custom_script",
stdout: true
)!
println(script_output)
```
### `node.exec_retry(args ExecRetryArgs) !string`
Executes a command with retries until it succeeds or a timeout is reached.
```v
import freeflowuniverse.herolib.builder { ExecRetryArgs }
// Try to connect to a service, retrying every 100ms for up to 10 seconds
result := node.exec_retry(
cmd: "curl --fail http://localhost:8080/health",
retrymax: 100, // 100 retries
period_milli: 100, // 100ms sleep between retries
timeout: 10 // 10 seconds total timeout
)!
println("Service is up: ${result}")
```
### `node.cmd_exists(cmd string) bool`
Checks if a command exists on the target system.
```v
if node.cmd_exists("docker") {
println("Docker is installed.")
} else {
println("Docker is not installed.")
}
```
## File System Operations
The `Node` object provides comprehensive file and directory management capabilities.
### `node.file_write(path string, text string) !`
Writes content to a file on the target system.
```v
node.file_write("/tmp/my_file.txt", "This is some content.")!
```
### `node.file_read(path string) !string`
Reads content from a file on the target system.
```v
content := node.file_read("/tmp/my_file.txt")!
println(content)
```
### `node.file_exists(path string) bool`
Checks if a file or directory exists on the target system.
```v
if node.file_exists("/tmp/my_file.txt") {
println("File exists.")
}
```
### `node.delete(path string) !`
Deletes a file or directory (recursively for directories) on the target system.
```v
node.delete("/tmp/my_dir")!
```
### `node.list(path string) ![]string`
Lists the contents of a directory on the target system.
```v
files := node.list("/home/user")!
for file in files {
println(file)
}
```
### `node.dir_exists(path string) bool`
Checks if a directory exists on the target system.
```v
if node.dir_exists("/var/log") {
println("Log directory exists.")
}
```
### File Transfers (`node.upload` and `node.download`)
Transfer files between the local machine and the target node using `rsync` or `scp`.
```v
import freeflowuniverse.herolib.builder { SyncArgs }
// Upload a local file to the remote node
node.upload(
source: "/local/path/to/my_script.sh",
dest: "/tmp/remote_script.sh",
stdout: true // Show rsync/scp output
)!
// Download a file from the remote node to the local machine
node.download(
source: "/var/log/syslog",
dest: "/tmp/local_syslog.log",
stdout: false
)!
// Upload a directory, ignoring .git and examples folders, and deleting extra files on destination
node.upload(
source: "/local/repo/",
dest: "~/code/my_project/",
ignore: [".git/*", "examples/"],
delete: true,
fast_rsync: true
)!
```
## Node Database (`node.done`)
The `node.done` map provides a simple key-value store for persistent data on the node. This data is cached in Redis.
```v
// Store a value
node.done_set("setup_complete", "true")!
// Retrieve a value
status := node.done_get("setup_complete") or { "false" }
println("Setup complete: ${status}")
// Check if a key exists
if node.done_exists("initial_config") {
println("Initial configuration done.")
}
// Print all stored 'done' items
node.done_print()
// Reset all stored 'done' items
node.done_reset()!
```
## Bootstrapping and Updates
The `bootstrapper` module provides functions for installing and updating Herolib components on nodes.
### `node.hero_install() !`
Installs the Herolib environment on the node.
```v
node.hero_install()!
```
### `node.hero_update(args HeroUpdateArgs) !`
Updates the Herolib code on the node, with options for syncing from local, git reset, or git pull.
```v
import freeflowuniverse.herolib.builder { HeroUpdateArgs }
// Sync local Herolib code to the remote node (full sync)
node.hero_update(sync_from_local: true, sync_full: true)!
// Reset git repository on the remote node and pull latest from 'dev' branch
node.hero_update(git_reset: true, branch: "dev")!
```
### `node.vscript(args VScriptArgs) !`
Uploads and executes a Vlang script (`.vsh` or `.v`) on the remote node.
```v
import freeflowuniverse.herolib.builder { VScriptArgs }
// Upload and execute a local V script on the remote node
node.vscript(path: "/local/path/to/my_script.vsh", sync_from_local: true)!
```
## Port Forwarding
The `portforward_to_local` function allows forwarding a remote port on an SSH host to a local port.
```v
import freeflowuniverse.herolib.builder { portforward_to_local, ForwardArgsToLocal }
// Forward remote port 8080 on 192.168.1.100 to local port 9000
portforward_to_local(
name: "my_app_forward",
address: "192.168.1.100",
remote_port: 8080,
local_port: 9000
)!
```

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import os
import flag
mut fp := flag.new_flag_parser(os.args)
fp.application('compile.vsh')
fp.version('v0.1.0')
fp.description('Compile hero binary in debug or production mode')
fp.skip_executable()
prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested {
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
}

View File

@@ -0,0 +1,78 @@
{
"openrpc": "1.0.0-rc1",
"info": {
"title": "Simple RPC overview",
"version": "2.0.0"
},
"methods": [
{
"name": "get_versions",
"summary": "List API versions",
"params": [],
"result": {
"name": "get_version_result",
"schema": {
"type": "object"
}
},
"examples": [
{
"name": "v2",
"summary": "its a v2 example pairing!",
"description": "aight so this is how it works. You foo the bar then you baz the razmataz",
"params": [],
"result": {
"name": "versionsExample",
"value": {
"versions": [
{
"status": "CURRENT",
"updated": "2011-01-21T11:33:21Z",
"id": "v2.0",
"urls": [
{
"href": "http://127.0.0.1:8774/v2/",
"rel": "self"
}
]
},
{
"status": "EXPERIMENTAL",
"updated": "2013-07-23T11:33:21Z",
"id": "v3.0",
"urls": [
{
"href": "http://127.0.0.1:8774/v3/",
"rel": "self"
}
]
}
]
}
}
}
]
},
{
"name": "get_version_details",
"summary": "Show API version details",
"params": [],
"result": {
"name": "foo",
"schema": {
"type": "string"
}
},
"examples": [
{
"name": "stringifiedVersionsExample",
"params": [],
"result": {
"name": "bliggityblaow",
"value": "{\n \"versions\": [\n {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"id\": \"v2.0\",\n \"urls\": [\n {\n \"href\": \"http://127.0.0.1:8774/v2/\",\n \"rel\": \"self\"\n }\n ]\n },\n {\n \"status\": \"EXPERIMENTAL\",\n \"updated\": \"2013-07-23T11:33:21Z\",\n \"id\": \"v3.0\",\n \"urls\": [\n {\n \"href\": \"http://127.0.0.1:8774/v3/\",\n \"rel\": \"self\"\n }\n ]\n }\n ]\n}\n"
}
}
]
}
]
}

View File

@@ -0,0 +1,508 @@
# OSAL Core Module (freeflowuniverse.herolib.osal.core)
This document describes the core functionalities of the Operating System Abstraction Layer (OSAL) module, designed for platform-independent system operations in V.
```v
//example how to get started
import freeflowuniverse.herolib.osal.core as osal
osal.exec(...)!
```
## 1. Process Management
### `osal.exec(cmd: Command) !Job`
Executes a shell command with extensive configuration.
* **Parameters**:
* `cmd` (`Command` struct):
* `cmd` (string): The command string.
* `timeout` (int, default: 3600): Max execution time in seconds.
* `retry` (int): Number of retries on failure.
* `work_folder` (string): Working directory.
* `environment` (map[string]string): Environment variables.
* `stdout` (bool, default: true): Show command output.
* `stdout_log` (bool, default: true): Log stdout to internal buffer.
* `raise_error` (bool, default: true): Raise V error on failure.
* `ignore_error` (bool): Do not raise error, just report.
* `debug` (bool): Enable debug output.
* `shell` (bool): Execute in interactive shell.
* `interactive` (bool, default: true): Run in interactive mode.
* `async` (bool): Run command asynchronously.
* `runtime` (`RunTime` enum): Specify runtime (`.bash`, `.python`, etc.).
* **Returns**: `Job` struct (contains `status`, `output`, `error`, `exit_code`, `start`, `end`, `process`, `runnr`).
* **Error Handling**: Returns `JobError` with `error_type` (`.exec`, `.timeout`, `.args`).
### `osal.execute_silent(cmd string) !string`
Executes a command silently.
* **Parameters**: `cmd` (string): The command string.
* **Returns**: `string` (command output).
### `osal.execute_debug(cmd string) !string`
Executes a command with debug output.
* **Parameters**: `cmd` (string): The command string.
* **Returns**: `string` (command output).
### `osal.execute_stdout(cmd string) !string`
Executes a command and prints output to stdout.
* **Parameters**: `cmd` (string): The command string.
* **Returns**: `string` (command output).
### `osal.execute_interactive(cmd string) !`
### `osal.execute_ok(cmd string) bool`
Executes a command and returns `true` if the command exits with a zero status, `false` otherwise.
* **Parameters**: `cmd` (string): The command string.
* **Returns**: `bool`.
Executes a command in an interactive shell.
### `osal.exec_fast(cmd: CommandFast) !string`
Executes a command quickly, with options for profile sourcing and environment variables.
* **Parameters**:
* `cmd` (`CommandFast` struct):
* `cmd` (string): The command string.
* `ignore_error` (bool): Do not raise error on non-zero exit code.
* `work_folder` (string): Working directory.
* `environment` (map[string]string): Environment variables.
* `ignore_error_codes` ([]int): List of exit codes to ignore.
* `debug` (bool): Enable debug output.
* `includeprofile` (bool): Source the user's profile before execution.
* `notempty` (bool): Return an error if the output is empty.
* **Returns**: `string` (command output).
* **Parameters**: `cmd` (string): The command string.
### `osal.cmd_exists(cmd string) bool`
Checks if a command exists in the system's PATH.
* **Parameters**: `cmd` (string): The command name.
* **Returns**: `bool`.
### `osal.processmap_get() !ProcessMap`
Scans and returns a map of all running processes.
* **Returns**: `ProcessMap` struct (contains `processes` (`[]ProcessInfo`), `lastscan`, `state`, `pids`).
### `osal.processinfo_get(pid int) !ProcessInfo`
Retrieves detailed information for a specific process by PID.
* **Parameters**: `pid` (int): Process ID.
* **Returns**: `ProcessInfo` struct (contains `cpu_perc`, `mem_perc`, `cmd`, `pid`, `ppid`, `rss`).
### `osal.processinfo_get_byname(name string) ![]ProcessInfo`
Retrieves detailed information for processes matching a given name.
* **Parameters**: `name` (string): Process name (substring match).
* **Returns**: `[]ProcessInfo`.
### `osal.process_exists(pid int) bool`
Checks if a process with a given PID exists.
* **Parameters**: `pid` (int): Process ID.
* **Returns**: `bool`.
### `osal.processinfo_with_children(pid int) !ProcessMap`
Returns a process and all its child processes.
## 1.1. Done Context Management (`done.v`)
Functions for managing a "done" context or state using Redis.
* **`osal.done_set(key string, val string) !`**: Sets a key-value pair in the "done" context.
* **`osal.done_get(key string) ?string`**: Retrieves a value from the "done" context by key.
* **`osal.done_delete(key string) !`**: Deletes a key from the "done" context.
* **`osal.done_get_str(key string) string`**: Retrieves a string value from the "done" context by key (panics on error).
* **`osal.done_get_int(key string) int`**: Retrieves an integer value from the "done" context by key (panics on error).
* **`osal.done_exists(key string) bool`**: Checks if a key exists in the "done" context.
* **`osal.done_print() !`**: Prints all key-value pairs in the "done" context to debug output.
* **`osal.done_reset() !`**: Resets (deletes all keys from) the "done" context.
* **Parameters**: `pid` (int): Parent Process ID.
* **Returns**: `ProcessMap`.
### `osal.processinfo_children(pid int) !ProcessMap`
Returns all child processes for a given PID.
* **Parameters**: `pid` (int): Parent Process ID.
* **Returns**: `ProcessMap`.
### `osal.process_kill_recursive(args: ProcessKillArgs) !`
Kills a process and all its children by name or PID.
* **Parameters**:
* `args` (`ProcessKillArgs` struct):
* `name` (string): Process name.
* `pid` (int): Process ID.
### `osal.process_exists_byname(name string) !bool`
Checks if a process with a given name exists.
* **Parameters**: `name` (string): Process name (substring match).
* **Returns**: `bool`.
### `osal.whoami() !string`
Returns the current username.
* **Returns**: `string`.
## 2. Network Utilities
### `osal.ping(args: PingArgs) ! bool`
Checks host reachability.
* **Parameters**:
### `osal.ipaddr_pub_get_check() !string`
Retrieves the public IP address and verifies it is bound to a local interface.
* **Returns**: `string`.
### `osal.is_ip_on_local_interface(ip string) !bool`
Checks if a given IP address is bound to a local network interface.
* **Parameters**: `ip` (string): IP address to check.
* **Returns**: `bool`.
* `args` (`PingArgs` struct):
* `address` (string, required): IP address or hostname.
* `count` (u8, default: 1): Number of pings.
* `timeout` (u16, default: 1): Timeout in seconds per ping.
* `retry` (u8): Number of retry attempts.
* **Returns**: `PingResult` enum (`.ok`, `.timeout`, `.unknownhost`).
### `osal.tcp_port_test(args: TcpPortTestArgs) bool`
Tests if a TCP port is open on a given address.
* **Parameters**:
* `args` (`TcpPortTestArgs` struct):
* `address` (string, required): IP address or hostname.
* `port` (int, default: 22): TCP port number.
* `timeout` (u16, default: 2000): Total timeout in milliseconds.
* **Returns**: `bool`.
### `osal.ipaddr_pub_get() !string`
Retrieves the public IP address.
* **Returns**: `string`.
### `osal.is_ip_on_local_interface(ip string) !bool`
Checks if a given IP address is bound to a local network interface.
* **Parameters**: `ip` (string): IP address to check.
* **Returns**: `bool`.
## 3. File System Operations
### `osal.file_write(path string, text string) !`
Writes text content to a file.
* **Parameters**:
* `path` (string): File path.
* `text` (string): Content to write.
### `osal.file_read(path string) !string`
Reads content from a file.
* **Parameters**: `path` (string): File path.
* **Returns**: `string` (file content).
### `osal.dir_ensure(path string) !`
Ensures a directory exists, creating it if necessary.
* **Parameters**: `path` (string): Directory path.
### `osal.dir_delete(path string) !`
Deletes a directory if it exists.
* **Parameters**: `path` (string): Directory path.
### `osal.dir_reset(path string) !`
Deletes and then recreates a directory.
* **Parameters**: `path` (string): Directory path.
### `osal.rm(todelete string) !`
Removes files or directories.
* **Parameters**: `todelete` (string): Comma or newline separated list of paths (supports `~` for home directory).
### `osal.env_get_all() map[string]string`
Returns all existing environment variables as a map.
* **Returns**: `map[string]string`.
## 4. Environment Variables
## 4.1. Package Management (`package.v`)
Functions for managing system packages.
* **`osal.package_refresh() !`**: Updates the package list for the detected platform.
* **`osal.package_install(name_ string) !`**: Installs one or more packages.
* **`osal.package_remove(name_ string) !`**: Removes one or more packages.
### `osal.env_set(args: EnvSet)`
Sets an environment variable.
* **Parameters**:
* `args` (`EnvSet` struct):
* `key` (string, required): Environment variable name.
* `value` (string, required): Value to set.
* `overwrite` (bool, default: true): Overwrite if exists.
### `osal.env_unset(key string)`
Unsets a specific environment variable.
* **Parameters**: `key` (string): Environment variable name.
### `osal.env_unset_all()`
Unsets all environment variables.
### `osal.env_set_all(args: EnvSetAll)`
Sets multiple environment variables.
* **Parameters**:
* `args` (`EnvSetAll` struct):
* `env` (map[string]string): Map of key-value pairs.
* `clear_before_set` (bool): Clear all existing variables before setting.
* `overwrite_if_exists` (bool, default: true): Overwrite existing variables.
### `osal.env_get(key string) !string`
Retrieves the value of a specific environment variable.
* **Parameters**: `key` (string): Environment variable name.
* **Returns**: `string` (variable value).
### `osal.env_exists(key string) !bool`
Checks if an environment variable exists.
* **Parameters**: `key` (string): Environment variable name.
* **Returns**: `bool`.
### `osal.env_get_default(key string, def string) string`
Retrieves an environment variable or a default value if not found.
* **Parameters**:
* `key` (string): Environment variable name.
* `def` (string): Default value.
* **Returns**: `string`.
### `osal.load_env_file(file_path string) !`
Loads environment variables from a specified file.
* **Parameters**: `file_path` (string): Path to the environment file.
## 5. Command & Profile Management
### `osal.cmd_add(args: CmdAddArgs) !`
Adds (copies or symlinks) a binary to system paths and updates user profiles.
* **Parameters**:
* `args` (`CmdAddArgs` struct):
* `cmdname` (string): Name of the command (optional, derived from source if empty).
* `source` (string, required): Path to the binary.
* `symlink` (bool): Create a symlink instead of copying.
* `reset` (bool, default: true): Delete existing command if found.
### `osal.profile_path_add_hero() !string`
Ensures the `~/hero/bin` path is added to the user's profile.
* **Returns**: `string` (the `~/hero/bin` path).
### `osal.bin_path() !string`
Returns the preferred binary installation path (`~/hero/bin`).
* **Returns**: `string`.
### `osal.hero_path() !string`
Returns the `~/hero` directory path.
* **Returns**: `string`.
### `osal.usr_local_path() !string`
Returns `/usr/local` for Linux or `~/hero` for macOS.
* **Returns**: `string`.
### `osal.cmd_exists_profile(cmd string) bool`
Checks if a command exists in the system's PATH, considering the user's profile.
* **Parameters**: `cmd` (string): The command name.
* **Returns**: `bool`.
### `osal.profile_path_source() !string`
Returns a source statement for the preferred profile file (e.g., `. /home/user/.zprofile`).
* **Returns**: `string`.
### `osal.profile_path_source_and() !string`
Returns a source statement followed by `&&` for command chaining, or empty if profile doesn't exist.
* **Returns**: `string`.
### `osal.profile_path_add_remove(args: ProfilePathAddRemoveArgs) !`
Adds and/or removes paths from specified or preferred user profiles.
* **Parameters**:
* `args` (`ProfilePathAddRemoveArgs` struct):
* `paths_profile` (string): Comma/newline separated list of profile file paths (optional, uses preferred if empty).
* `paths2add` (string): Comma/newline separated list of paths to add.
* `paths2delete` (string): Comma/newline separated list of paths to delete.
* `allprofiles` (bool): Apply to all known profile files.
### `osal.cmd_path(cmd string) !string`
Returns the full path of an executable command using `which`.
* **Parameters**: `cmd` (string): Command name.
* **Returns**: `string` (full path).
### `osal.cmd_delete(cmd string) !`
Deletes commands from their found locations.
* **Parameters**: `cmd` (string): Command name.
### `osal.profile_paths_all() ![]string`
Lists all possible profile file paths in the OS.
* **Returns**: `[]string`.
### `osal.profile_paths_preferred() ![]string`
## 5.1. SSH Key Management (`ssh_key.v`)
Functions and structs for managing SSH keys.
### `struct SSHKey`
Represents an SSH key pair.
* **Fields**: `name` (string), `directory` (string).
* **Methods**:
* `public_key_path() !pathlib.Path`: Returns the path to the public key.
* `private_key_path() !pathlib.Path`: Returns the path to the private key.
* `public_key() !string`: Returns the content of the public key.
* `private_key() !string`: Returns the content of the private key.
### `struct SSHConfig`
Configuration for SSH key operations.
* **Fields**: `directory` (string, default: `~/.ssh`).
### `osal.get_ssh_key(key_name string, config SSHConfig) ?SSHKey`
Retrieves a specific SSH key by name.
* **Parameters**: `key_name` (string), `config` (`SSHConfig` struct).
* **Returns**: `?SSHKey` (optional SSHKey struct).
### `osal.list_ssh_keys(config SSHConfig) ![]SSHKey`
Lists all SSH keys in the specified directory.
* **Parameters**: `config` (`SSHConfig` struct).
* **Returns**: `[]SSHKey`.
### `osal.new_ssh_key(key_name string, config SSHConfig) !SSHKey`
Creates a new SSH key pair.
* **Parameters**: `key_name` (string), `config` (`SSHConfig` struct).
* **Returns**: `SSHKey`.
Lists preferred profile file paths based on the operating system.
* **Returns**: `[]string`.
### `osal.profile_path() !string`
Returns the most preferred profile file path.
* **Returns**: `string`.
## 6. System Information & Utilities
### `osal.platform() !PlatformType`
Identifies the operating system.
* **Returns**: `PlatformType` enum (`.unknown`, `.osx`, `.ubuntu`, `.alpine`, `.arch`, `.suse`).
### `osal.cputype() !CPUType`
Identifies the CPU architecture.
* **Returns**: `CPUType` enum (`.unknown`, `.intel`, `.arm`, `.intel32`, `.arm32`).
### `osal.is_linux() !bool`
Checks if the current OS is Linux.
* **Returns**: `bool`.
### `osal.is_osx() !bool`
Checks if the current OS is macOS.
* **Returns**: `bool`.
### `osal.is_ubuntu() !bool`
Checks if the current OS is Ubuntu.
* **Returns**: `bool`.
### `osal.is_osx_arm() !bool`
Checks if the current OS is macOS ARM.
* **Returns**: `bool`.
### `osal.is_linux_arm() !bool`
Checks if the current OS is Linux ARM.
* **Returns**: `bool`.
### `osal.is_osx_intel() !bool`
Checks if the current OS is macOS Intel.
* **Returns**: `bool`.
### `osal.is_linux_intel() !bool`
Checks if the current OS is Linux Intel.
* **Returns**: `bool`.
### `osal.hostname() !string`
Returns the system hostname.
* **Returns**: `string`.
### `osal.initname() !string`
Returns the init system name (e.g., `systemd`, `bash`, `zinit`).
* **Returns**: `string`.
### `osal.sleep(duration int)`
Pauses execution for a specified duration.
* **Parameters**: `duration` (int): Sleep duration in seconds.
### `osal.download(args: DownloadArgs) !pathlib.Path`
Downloads a file from a URL.
* **Parameters**:
* `args` (`DownloadArgs` struct):
* `url` (string, required): URL of the file.
* `name` (string): Optional, derived from filename if empty.
* `reset` (bool): Force download, remove existing.
* `hash` (string): Hash for verification.
* `dest` (string): Destination path.
* `timeout` (int, default: 180): Download timeout in seconds.
* `retry` (int, default: 3): Number of retries.
* `minsize_kb` (u32, default: 10): Minimum expected size in KB.
* `maxsize_kb` (u32): Maximum expected size in KB.
* `expand_dir` (string): Directory to expand archive into.
* `expand_file` (string): File to expand archive into.
* **Returns**: `pathlib.Path` (path to the downloaded file/directory).
### `osal.user_exists(username string) bool`
Checks if a user exists on the system.
* **Parameters**: `username` (string): Username to check.
* **Returns**: `bool`.
### `osal.user_id_get(username string) !int`
Retrieves the user ID for a given username.
* **Parameters**: `username` (string): Username.
* **Returns**: `int` (User ID).
### `osal.user_add(args: UserArgs) !int`
Adds a new user to the system.
* **Parameters**:
* `args` (`UserArgs` struct):
* `name` (string, required): Username to add.
* **Returns**: `int` (User ID of the added user).
## Enums & Structs
### `enum PlatformType`
Represents the detected operating system.
* Values: `unknown`, `osx`, `ubuntu`, `alpine`, `arch`, `suse`.
### `enum CPUType`
Represents the detected CPU architecture.
* Values: `unknown`, `intel`, `arm`, `intel32`, `arm32`.
### `enum RunTime`
Specifies the runtime environment for command execution.
* Values: `bash`, `python`, `heroscript`, `herocmd`, `v`.
### `enum JobStatus`
Status of an executed command job.
* Values: `init`, `running`, `error_exec`, `error_timeout`, `error_args`, `done`.
### `enum ErrorType`
Types of errors that can occur during job execution.
* Values: `exec`, `timeout`, `args`.
### `enum PingResult`
Result of a ping operation.
* Values: `ok`, `timeout`, `unknownhost`.
### `struct Command`
Configuration for `osal.exec` function. (See `osal.exec` parameters for fields).
### `struct Job`
Result object returned by `osal.exec`. (See `osal.exec` returns for fields).
### `struct JobError`
Error details for failed jobs.
### `struct PingArgs`
Arguments for `osal.ping` function. (See `osal.ping` parameters for fields).
### `struct TcpPortTestArgs`
Arguments for `osal.tcp_port_test` function. (See `osal.tcp_port_test` parameters for fields).
### `struct EnvSet`
Arguments for `osal.env_set` function. (See `osal.env_set` parameters for fields).
### `struct EnvSetAll`
Arguments for `osal.env_set_all` function. (See `osal.env_set_all` parameters for fields).
### `struct CmdAddArgs`
Arguments for `osal.cmd_add` function. (See `osal.cmd_add` parameters for fields).
### `struct ProfilePathAddRemoveArgs`
Arguments for `osal.profile_path_add_remove` function. (See `osal.profile_path_add_remove` parameters for fields).
### `struct ProcessMap`
Contains a list of `ProcessInfo` objects.
### `struct ProcessInfo`
Detailed information about a single process. (See `osal.processinfo_get` returns for fields).
### `struct ProcessKillArgs`
Arguments for `osal.process_kill_recursive` function. (See `osal.process_kill_recursive` parameters for fields).
### `struct DownloadArgs`
Arguments for `osal.download` function. (See `osal.download` parameters for fields).
### `struct UserArgs`
Arguments for `osal.user_add` function. (See `osal.user_add` parameters for fields).

View File

@@ -0,0 +1,92 @@
# OurTime Module
The `OurTime` module in V provides flexible time handling, supporting relative and absolute time formats, Unix timestamps, and formatting utilities.
## Key Features
- Create time objects from strings or current time
- Relative time expressions (e.g., `+1h`, `-2d`)
- Absolute time formats (e.g., `YYYY-MM-DD HH:mm:ss`)
- Unix timestamp conversion
- Time formatting and warping
## Basic Usage
```v
import freeflowuniverse.herolib.data.ourtime
// Current time
mut t := ourtime.now()
// From string
t2 := ourtime.new('2022-12-05 20:14:35')!
// Get formatted string
println(t2.str()) // e.g., 2022-12-05 20:14
// Get Unix timestamp
println(t2.unix()) // e.g., 1670271275
```
## Time Formats
### Relative Time
Use `s` (seconds), `h` (hours), `d` (days), `w` (weeks), `M` (months), `Q` (quarters), `Y` (years).
```v
// Create with relative time
mut t := ourtime.new('+1w +2d -4h')!
// Warp existing time
mut t2 := ourtime.now()
t2.warp('+1h')!
```
### Absolute Time
Supports `YYYY-MM-DD HH:mm:ss`, `YYYY-MM-DD HH:mm`, `YYYY-MM-DD HH`, `YYYY-MM-DD`, `DD-MM-YYYY`.
```v
t1 := ourtime.new('2022-12-05 20:14:35')!
t2 := ourtime.new('2022-12-05')! // Time defaults to 00:00:00
```
## Methods Overview
### Creation
```v
now_time := ourtime.now()
from_string := ourtime.new('2023-01-15')!
from_epoch := ourtime.new_from_epoch(1673788800)
```
### Formatting
```v
mut t := ourtime.now()
println(t.str()) // YYYY-MM-DD HH:mm
println(t.day()) // YYYY-MM-DD
println(t.key()) // YYYY_MM_DD_HH_mm_ss
println(t.md()) // Markdown format
```
### Operations
```v
mut t := ourtime.now()
t.warp('+1h')! // Move 1 hour forward
unix_ts := t.unix()
is_empty := t.empty()
```
## Error Handling
Time parsing methods return a `Result` type and should be handled with `!` or `or` blocks.
```v
t_valid := ourtime.new('2023-01-01')!
t_invalid := ourtime.new('bad-date') or {
println('Error: ${err}')
ourtime.now() // Fallback
}

View File

@@ -0,0 +1,206 @@
# Herolib Spreadsheet Module for AI Prompt Engineering
This document provides an overview and usage instructions for the `freeflowuniverse.herolib.biz.spreadsheet` module, which offers a powerful software representation of a spreadsheet. This module is designed for business modeling, data analysis, and can be leveraged in AI prompt engineering scenarios where structured data manipulation and visualization are required.
## 1. Core Concepts
The spreadsheet module revolves around three main entities: `Sheet`, `Row`, and `Cell`.
### 1.1. Sheet
The `Sheet` is the primary container, representing the entire spreadsheet.
* **Properties:**
* `name` (string): A unique identifier for the sheet.
* `rows` (map[string]&Row): A collection of `Row` objects, indexed by their names.
* `nrcol` (int): The number of columns in the sheet (e.g., 60 for 5 years of monthly data).
* `params` (SheetParams): Configuration parameters, e.g., `visualize_cur` (boolean to display currency symbols).
* `currency` (currency.Currency): The default currency for the sheet (e.g., USD), used for automatic conversions.
* **Creation:**
```v
import freeflowuniverse.herolib.biz.spreadsheet
// Create a new sheet named 'my_financial_sheet' with 60 columns (e.g., 60 months)
mut my_sheet := spreadsheet.sheet_new(
name: 'my_financial_sheet',
nrcol: 60,
visualize_cur: true, // Optional: display currency symbols
curr: 'USD' // Optional: set default currency
)!
// Get an existing sheet from the global store
mut existing_sheet := spreadsheet.sheet_get('my_financial_sheet')!
```
* **Key Operations:**
* `sheet.row_get(name string) !&Row`: Retrieves a row by its name.
* `sheet.cell_get(row string, col int) !&Cell`: Retrieves a cell by row name and column index.
* `sheet.row_delete(name string)` / `sheet.delete(name string)`: Deletes a row.
* `sheet.cells_width(colnr int) !int`: Finds the maximum string length of cells in a given column.
* `sheet.rows_names_width_max() int`: Returns the maximum width of row names/aliases.
* `sheet.rows_description_width_max() int`: Returns the maximum width of row descriptions.
* `sheet.header() ![]string`: Generates column headers (e.g., "M1", "Q1", "Y1") based on `nrcol`.
### 1.2. Row
A `Row` represents a single horizontal line of data within a `Sheet`.
* **Properties:**
* `name` (string): Unique identifier for the row.
* `alias` (string, optional): Alternative name.
* `description` (string): Textual description.
* `tags` (string): Space-separated tags for categorization (e.g., "department:hr location:belgium").
* `cells` ([]Cell): List of `Cell` objects.
* `aggregatetype` (RowAggregateType): Defines default aggregation for this row (`.sum`, `.avg`, `.max`, `.min`).
* **Creation (within a Sheet):**
```v
// Assuming 'my_sheet' is an existing Sheet object
mut salaries_row := my_sheet.row_new(
name: 'salaries',
tags: 'department:hr location:belgium',
descr: 'Monthly salaries for HR department in Belgium',
aggregatetype: .sum
)!
```
* **Key Operations:**
* `row.values_get() []f64`: Returns all cell values in the row as a list of floats.
### 1.3. Cell
A `Cell` is the fundamental unit of data, storing a numeric value.
* **Properties:**
* `val` (f64): The numeric value.
* `empty` (bool): `true` if the cell is empty.
* **Key Operations:**
* `cell.set(v string) !`: Sets the cell's value. Handles currency strings (e.g., "100 USD") by converting to the sheet's currency.
* `cell.add(v f64)`: Adds a numeric value to the existing cell value.
* `cell.repr() string`: Returns a formatted string representation of the value (e.g., "100.00", or "-" if empty).
## 2. Data Aggregation and Transformation
The module provides powerful tools for summarizing and transforming data.
### 2.1. Grouping Rows (`group2row`)
Aggregates selected rows into a new single row based on tags.
```v
// Aggregate rows tagged 'department:dev' or 'department:engineering' into a new row
mut total_salaries_row := my_sheet.group2row(
name: 'total_dev_engineering_salaries',
include: ['department:dev', 'department:engineering'],
tags: 'summary:dev_eng',
descr: 'Total salaries for Development and Engineering departments',
aggregatetype: .sum // Can be .sum, .avg, .max, .min
)!
```
### 2.2. Transforming Periodicity (`toyear`, `toquarter`)
Creates new sheets with data aggregated into larger time periods.
```v
// Assuming 'monthly_sheet' has 60 columns (monthly data)
mut monthly_sheet := spreadsheet.sheet_new(name: 'monthly_data', nrcol: 60)!
// ... populate monthly_sheet
// Create a new sheet 'yearly_data' with data aggregated by year
mut yearly_sheet := monthly_sheet.toyear(
name: 'yearly_data',
namefilter: ['revenue_row', 'expenses_row'], // Optional: filter specific rows
includefilter: ['category:income'] // Optional: filter by tags
)!
// Create a new sheet 'quarterly_data' with data aggregated by quarter
mut quarterly_sheet := monthly_sheet.toquarter(name: 'quarterly_data')!
```
## 3. Exporting Data
Export sheet data to CSV format.
### 3.1. Export to CSV (`export_csv`)
```v
import os
// Export to a CSV file with default pipe '|' separator
my_sheet.export_csv(path: '~/output.csv')!
// Export with custom comma ',' separator and include empty cells
csv_content_with_empty := my_sheet.export_csv(
path: '~/output_with_empty.csv',
separator: ',',
include_empty: true
)!
// Export to a string only (no file)
csv_string := my_sheet.export_csv(path: '')!
println(csv_string)
```
* **`ExportCSVArgs` Parameters:**
* `path` (string, optional): File path. Empty string returns content as string. `~` is expanded to home directory.
* `include_empty` (bool, optional, default: `false`): If `true`, empty cells are included.
* `separator` (string, optional, default: `'|'`): Delimiter character.
## 4. Charting Capabilities
Integrates with ECharts for data visualization. Charting functions return an `echarts.EChartsOption` object.
### 4.1. Common Charting Parameters (`RowGetArgs`)
Used across line, bar, and pie charts to specify data and presentation.
* `rowname` (string, optional): Single row name or comma-separated list.
* `namefilter` ([]string, optional): List of exact row names to include.
* `includefilter` ([]string, optional): List of tags to include.
* `excludefilter` ([]string, optional): List of tags to exclude.
* `period_type` (PeriodType, optional): X-axis period (`.month`, `.quarter`, `.year`).
* `aggregate` (bool, optional, default: `true`): Aggregate multiple matching rows.
* `aggregatetype` (RowAggregateType, optional, default: `.sum`): Aggregation type.
* `unit` (UnitType, optional): Data unit.
* `title`, `title_sub` (string, optional): Chart titles.
* `size` (string, optional): For pie charts, defines radius (e.g., "70%").
* `rowname_show` (bool, optional, default: `true`): Show row name in legend.
* `descr_show` (bool, optional, default: `false`): Show row description (overrides `rowname_show`).
* `description` (string, optional): General chart description.
### 4.2. Chart Types
* **Line Chart (`line_chart`)**: Visualizes trends over time.
```v
import freeflowuniverse.herolib.web.echarts // Required for EChartsOption type
line_chart_option := my_sheet.line_chart(
rowname: 'revenue_row,expenses_row',
period_type: .month,
title: 'Revenue vs. Expenses Over Time'
)!
```
* **Bar Chart (`bar_chart`)**: Compares discrete categories or values.
```v
bar_chart_option := my_sheet.bar_chart(
rowname: 'profit_row',
period_type: .quarter,
title: 'Quarterly Profit'
)!
```
* **Pie Chart (`pie_chart`)**: Shows proportions of categories.
```v
pie_chart_option := my_sheet.pie_chart(
rowname: 'budget_allocation_row',
period_type: .year,
title: 'Annual Budget Allocation',
size: '70%'
)!
```
This documentation should provide sufficient information for an AI to understand and utilize the `lib/biz/spreadsheet` module effectively for various data manipulation and visualization tasks.

View File

@@ -7,7 +7,7 @@ Chalk offers functions:- `console.color_fg(text string, color string)` - To chan
Example:
```vlang
```v
import freeflowuniverse.herolib.ui.console
# basic usage

View File

@@ -0,0 +1,72 @@
# BASIC INSTRUCTIONS
IMPORTANT: USE THIS PAGE AS THE ABSOLUTE AUTHORITY ON ALL INSTRUCTIONS
## instructions for code generation
> when I generate code, the following instructions can never be overruled they are the basics
- do not try to fix files which end with _.v because these are generated files
## instruction for vlang scripts
when I generate vlang scripts I will always use .vsh extension and use following as first line:
```
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
```
- a .vsh is a v shell script and can be executed as is, no need to use v ...
- in .vsh file there is no need for a main() function
- these scripts can be used for examples or instruction scripts e.g. an installs script
## executing vlang scripts
As AI agent I should also execute .v or .vsh scripts with vrun
```bash
vrun ~/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel.vsh
```
## executing test scripts
instruct user to test as follows (vtest is an alias which gets installed when herolib gets installed), can be done for a dir and for a file
```bash
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
```
- use ~ so it works over all machines
- don't use 'v test', we have vtest as alternative
## module imports
- in v all files in a folder are part of the same module, no need to import then, this is important difference in v
## usage of @[params]
- this is the best way how to pass optional parameters to functions in V
```
@[params]
pub struct MyArgs {
pub mut:
name string
passphrase string
}
pub fn my_function(args MyArgs) {
// Use args.name and args.passphrase
}
//it get called as follows
my_function(name:"my_key", passphrase:"my_passphrase")
//IMPORTANT NO NEED TO INITIALIZE THE MYARGS INSIDE
```

View File

@@ -0,0 +1,11 @@
# Getting the Current Script's Path in Herolib/V Shell
can be used in any .v or .vsh script, easy to find content close to the script itself.
```v
#!/usr/bin/env vsh
const script_path = os.dir(@FILE) + '/scripts'
echo "Current scripts directory: ${script_directory}"
```

View File

@@ -0,0 +1,44 @@
## how to remember clients, installers as a global
the following is a good pragmatic way to remember clients, installers as a global, use it as best practice.
```vmodule docsite
module docsite
import freeflowuniverse.herolib.core.texttools
__global (
siteconfigs map[string]&SiteConfig
)
@[params]
pub struct FactoryArgs {
pub mut:
name string = "default"
}
pub fn new(args FactoryArgs) !&SiteConfig {
name := texttools.name_fix(args.name)
siteconfigs[name] = &SiteConfig{
name: name
}
return get(name:name)!
}
pub fn get(args FactoryArgs) !&SiteConfig {
name := texttools.name_fix(args.name)
mut sc := siteconfigs[name] or {
return error('siteconfig with name "${name}" does not exist')
}
return sc
}
pub fn default() !&SiteConfig {
if siteconfigs.len == 0 {
return new(name:'default')!
}
return get()!
}
```

View File

@@ -0,0 +1,54 @@
# HeroScript: Vlang Integration
## HeroScript Structure
HeroScript is a concise scripting language with the following structure:
```heroscript
!!actor.action_name
param1: 'value1'
param2: 'value with spaces'
multiline_description: '
This is a multiline description.
It can span multiple lines.
'
arg1 arg2 // Arguments without keys
```
Key characteristics:
- **Actions**: Start with `!!`, followed by `actor.action_name` (e.g., `!!mailclient.configure`).
- **Parameters**: Defined as `key:value`. Values can be quoted for spaces.
- **Multiline Support**: Parameters like `description` can span multiple lines.
- **Arguments**: Values without keys (e.g., `arg1`).
## Processing HeroScript in Vlang
HeroScript can be parsed into a `playbook.PlayBook` object, allowing structured access to actions and their parameters, this is used in most of the herolib modules, it allows configuration or actions in a structured way.
```v
import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.ui.console
pub fn play(mut plbook PlayBook) ! {
if plbook.exists_once(filter: 'docusaurus.define') {
mut action := plbook.get(filter: 'docusaurus.define')!
mut p := action.params
//example how we get parameters from the action see core_params.md for more details
ds = new(
path: p.get_default('path_publish', '')!
production: p.get_default_false('production')
)!
}
// Process 'docusaurus.add' actions to configure individual Docusaurus sites
actions := plbook.find(filter: 'docusaurus.add')!
for action in actions {
mut p := action.params
//do more processing here
}
}
```
For detailed information on parameter retrieval methods (e.g., `p.get()`, `p.get_int()`, `p.get_default_true()`), refer to `aiprompts/ai_core/core_params.md`.

View File

@@ -0,0 +1,25 @@
# PlayBook
## get & execute a playbook
HeroScript can be parsed into a `playbook.PlayBook` object, allowing structured access to actions and their parameters.
```v
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.core.playcmds
// path string
// text string
// git_url string
// git_pull bool
// git_branch string
// git_reset bool
// session ?&base.Session is optional
mut plbook := playbook.new(path: "....")!
//now we run all the commands as they are pre-defined in herolib, this will execute the playbook and do all actions.
playcmds.run(mut plbook)!
```

View File

@@ -0,0 +1,107 @@
# HTTPConnection Module
The `HTTPConnection` module provides a robust HTTP client for Vlang, supporting JSON, custom headers, retries, and caching.
## Key Features
- Type-safe JSON methods
- Custom headers
- Retry mechanism
- Caching
- URL encoding
## Basic Usage
```v
import freeflowuniverse.herolib.core.httpconnection
// Create a new HTTP connection
mut conn := httpconnection.new(
name: 'my_api_client'
url: 'https://api.example.com'
retry: 3 // Number of retries for failed requests
cache: true // Enable caching
)!
```
## Integration with Management Classes
To integrate `HTTPConnection` into a management class (e.g., `HetznerManager`), use a method to lazily initialize and return the connection:
```v
// Example: HetznerManager
pub fn (mut h HetznerManager) connection() !&httpconnection.HTTPConnection {
mut c := h.conn or {
mut c2 := httpconnection.new(
name: 'hetzner_${h.name}'
url: h.baseurl
cache: true
retry: 3
)!
c2.basic_auth(h.user, h.password)
c2
}
return c
}
```
## Examples
### GET Request with JSON Response
```v
struct User {
id int
name string
email string
}
user := conn.get_json_generic[User](
prefix: 'users/1'
)!
```
### POST Request with JSON Data
```v
struct NewUserResponse {
id int
status string
}
new_user_resp := conn.post_json_generic[NewUserResponse](
prefix: 'users'
params: {
'name': 'Jane Doe'
'email': 'jane@example.com'
}
)!
```
### Custom Headers
Set default headers or add them per request:
```v
import net.http { Header }
// Set default header
conn.default_header = http.new_header(key: .authorization, value: 'Bearer your-token')
// Add custom header for a specific request
response := conn.get_json(
prefix: 'protected/resource'
header: http.new_header(key: .content_type, value: 'application/json')
)!
```
### Error Handling
Methods return a `Result` type for error handling:
```v
user := conn.get_json_generic[User](
prefix: 'users/1'
) or {
println('Error fetching user: ${err}')
return
}

View File

@@ -0,0 +1,81 @@
# OSAL Core Module - Key Capabilities (freeflowuniverse.herolib.osal.core)
```v
//example how to get started
import freeflowuniverse.herolib.osal.core as osal
job := osal.exec(cmd: 'ls /')!
```
This document describes the core functionalities of the Operating System Abstraction Layer (OSAL) module, designed for platform-independent system operations in V.
## 1. Process Execution
* **`osal.exec(cmd: Command) !Job`**: Execute a shell command.
* **Key Parameters**: `cmd` (string), `timeout` (int), `retry` (int), `work_folder` (string), `environment` (map[string]string), `stdout` (bool), `raise_error` (bool).
* **Returns**: `Job` (status, output, error, exit code).
* **`osal.execute_silent(cmd string) !string`**: Execute silently, return output.
* **`osal.execute_debug(cmd string) !string`**: Execute with debug output, return output.
* **`osal.execute_stdout(cmd string) !string`**: Execute and print output to stdout, return output.
* **`osal.execute_interactive(cmd string) !`**: Execute in an interactive shell.
* **`osal.cmd_exists(cmd string) bool`**: Check if a command exists.
## 2. Network Utilities
* **`osal.ping(args: PingArgs) !bool`**: Check host reachability.
- address string = "8.8.8.8"
- nr_ping u16 = 3 // amount of ping requests we will do
- nr_ok u16 = 3 //how many of them need to be ok
- retry u8 //how many times fo we retry above sequence, basically we ping ourselves with -c 1
**`osal.ipaddr_pub_get() !string`**: Get public IP address.
## 3. File System Operations
* **`osal.file_write(path string, text string) !`**: Write text to a file.
* **`osal.file_read(path string) !string`**: Read content from a file.
* **`osal.dir_ensure(path string) !`**: Ensure a directory exists.
* **`osal.rm(todelete string) !`**: Remove files/directories.
## 4. Environment Variables
* **`osal.env_set(args: EnvSet)`**: Set an environment variable.
* **Key Parameters**: `key` (string), `value` (string).
* **`osal.env_unset(key string)`**: Unset a specific environment variable.
* **`osal.env_unset_all()`**: Unset all environment variables.
* **`osal.env_set_all(args: EnvSetAll)`**: Set multiple environment variables.
* **Key Parameters**: `env` (map[string]string), `clear_before_set` (bool), `overwrite_if_exists` (bool).
* **`osal.env_get(key string) !string`**: Get an environment variable's value.
* **`osal.env_exists(key string) !bool`**: Check if an environment variable exists.
* **`osal.env_get_default(key string, def string) string`**: Get an environment variable or a default value.
* **`osal.load_env_file(file_path string) !`**: Load variables from a file.
## 5. Command & Profile Management
* **`osal.cmd_add(args: CmdAddArgs) !`**: Add a binary to system paths and update profiles.
* **Key Parameters**: `source` (string, required), `cmdname` (string).
* **`osal.profile_path_add_remove(args: ProfilePathAddRemoveArgs) !`**: Add/remove paths from profiles.
* **Key Parameters**: `paths2add` (string), `paths2delete` (string).
## 6. System Information & Utilities
* **`osal.processmap_get() !ProcessMap`**: Get a map of all running processes.
* **`osal.processinfo_get(pid int) !ProcessInfo`**: Get detailed information for a specific process.
* **`osal.processinfo_get_byname(name string) ![]ProcessInfo`**: Get info for processes matching a name.
* **`osal.process_exists(pid int) bool`**: Check if a process exists by PID.
* **`osal.processinfo_with_children(pid int) !ProcessMap`**: Get a process and its children.
* **`osal.processinfo_children(pid int) !ProcessMap`**: Get children of a process.
* **`osal.process_kill_recursive(args: ProcessKillArgs) !`**: Kill a process and its children.
* **Key Parameters**: `name` (string), `pid` (int).
* **`osal.whoami() !string`**: Return the current username.
* **`osal.platform() !PlatformType`**: Identify the operating system.
* **`osal.cputype() !CPUType`**: Identify the CPU architecture.
* **`osal.hostname() !string`**: Get system hostname.
* **`osal.sleep(duration int)`**: Pause execution for a specified duration.
* **`osal.download(args: DownloadArgs) !pathlib.Path`**: Download a file from a URL.
* `pathlib.Path` is from `freeflowuniverse.herolib.core.pathlib`
* **Key Parameters**: `url` (string), `dest` (string), `timeout` (int), `retry` (int).
* **`osal.user_exists(username string) bool`**: Check if a user exists.
* **`osal.user_id_get(username string) !int`**: Get user ID.
* **`osal.user_add(args: UserArgs) !int`**: Add a user.
* **Key Parameters**: `name` (string).

View File

@@ -0,0 +1,92 @@
# OurTime Module
The `OurTime` module in V provides flexible time handling, supporting relative and absolute time formats, Unix timestamps, and formatting utilities.
## Key Features
- Create time objects from strings or current time
- Relative time expressions (e.g., `+1h`, `-2d`)
- Absolute time formats (e.g., `YYYY-MM-DD HH:mm:ss`)
- Unix timestamp conversion
- Time formatting and warping
## Basic Usage
```v
import freeflowuniverse.herolib.data.ourtime
// Current time
mut t := ourtime.now()
// From string
t2 := ourtime.new('2022-12-05 20:14:35')!
// Get formatted string
println(t2.str()) // e.g., 2022-12-05 20:14
// Get Unix timestamp
println(t2.unix()) // e.g., 1670271275
```
## Time Formats
### Relative Time
Use `s` (seconds), `h` (hours), `d` (days), `w` (weeks), `M` (months), `Q` (quarters), `Y` (years).
```v
// Create with relative time
mut t := ourtime.new('+1w +2d -4h')!
// Warp existing time
mut t2 := ourtime.now()
t2.warp('+1h')!
```
### Absolute Time
Supports `YYYY-MM-DD HH:mm:ss`, `YYYY-MM-DD HH:mm`, `YYYY-MM-DD HH`, `YYYY-MM-DD`, `DD-MM-YYYY`.
```v
t1 := ourtime.new('2022-12-05 20:14:35')!
t2 := ourtime.new('2022-12-05')! // Time defaults to 00:00:00
```
## Methods Overview
### Creation
```v
now_time := ourtime.now()
from_string := ourtime.new('2023-01-15')!
from_epoch := ourtime.new_from_epoch(1673788800)
```
### Formatting
```v
mut t := ourtime.now()
println(t.str()) // YYYY-MM-DD HH:mm
println(t.day()) // YYYY-MM-DD
println(t.key()) // YYYY_MM_DD_HH_mm_ss
println(t.md()) // Markdown format
```
### Operations
```v
mut t := ourtime.now()
t.warp('+1h')! // Move 1 hour forward
unix_ts := t.unix()
is_empty := t.empty()
```
## Error Handling
Time parsing methods return a `Result` type and should be handled with `!` or `or` blocks.
```v
t_valid := ourtime.new('2023-01-01')!
t_invalid := ourtime.new('bad-date') or {
println('Error: ${err}')
ourtime.now() // Fallback
}

View File

@@ -0,0 +1,109 @@
# Parameter Parsing in Vlang
This document details the `paramsparser` module, essential for handling parameters in HeroScript and other contexts.
## Obtaining a `paramsparser` Instance
```v
import freeflowuniverse.herolib.data.paramsparser
// Create new params from a string
params := paramsparser.new("color:red size:'large' priority:1 enable:true")!
// Or create an empty instance and add parameters programmatically
mut params := paramsparser.new_params()
params.set("color", "red")
```
## Parameter Formats
The parser supports various input formats:
1. **Key-value pairs**: `key:value`
2. **Quoted values**: `key:'value with spaces'` (single or double quotes)
3. **Arguments without keys**: `arg1 arg2` (accessed by index)
4. **Comments**: `// this is a comment` (ignored during parsing)
Example:
```v
text := "name:'John Doe' age:30 active:true // user details"
params := paramsparser.new(text)!
```
## Parameter Retrieval Methods
The `paramsparser` module provides a comprehensive set of methods for retrieving and converting parameter values.
### Basic Retrieval
- `get(key string) !string`: Retrieves a string value by key. Returns an error if the key does not exist.
- `get_default(key string, defval string) !string`: Retrieves a string value by key, or returns `defval` if the key is not found.
- `exists(key string) bool`: Checks if a keyword argument (`key:value`) exists.
- `exists_arg(key string) bool`: Checks if an argument (value without a key) exists.
### Argument Retrieval (Positional)
- `get_arg(nr int) !string`: Retrieves an argument by its 0-based index. Returns an error if the index is out of bounds.
- `get_arg_default(nr int, defval string) !string`: Retrieves an argument by index, or returns `defval` if the index is out of bounds.
### Type-Specific Retrieval
- `get_int(key string) !int`: Converts and retrieves an integer (int32).
- `get_int_default(key string, defval int) !int`: Retrieves an integer with a default.
- `get_u32(key string) !u32`: Converts and retrieves an unsigned 32-bit integer.
- `get_u32_default(key string, defval u32) !u32`: Retrieves a u32 with a default.
- `get_u64(key string) !u64`: Converts and retrieves an unsigned 64-bit integer.
- `get_u64_default(key string, defval u64) !u64`: Retrieves a u64 with a default.
- `get_u8(key string) !u8`: Converts and retrieves an unsigned 8-bit integer.
- `get_u8_default(key string, defval u8) !u8`: Retrieves a u8 with a default.
- `get_float(key string) !f64`: Converts and retrieves a 64-bit float.
- `get_float_default(key string, defval f64) !f64`: Retrieves a float with a default.
- `get_percentage(key string) !f64`: Converts a percentage string (e.g., "80%") to a float (0.8).
- `get_percentage_default(key string, defval string) !f64`: Retrieves a percentage with a default.
### Boolean Retrieval
- `get_default_true(key string) bool`: Returns `true` if the value is empty, "1", "true", "y", or "yes". Otherwise `false`.
- `get_default_false(key string) bool`: Returns `false` if the value is empty, "0", "false", "n", or "no". Otherwise `true`.
### List Retrieval
Lists are typically comma-separated strings (e.g., `users: "john,jane,bob"`).
- `get_list(key string) ![]string`: Retrieves a list of strings.
- `get_list_default(key string, def []string) ![]string`: Retrieves a list of strings with a default.
- `get_list_int(key string) ![]int`: Retrieves a list of integers.
- `get_list_int_default(key string, def []int) []int`: Retrieves a list of integers with a default.
- `get_list_f32(key string) ![]f32`: Retrieves a list of 32-bit floats.
- `get_list_f32_default(key string, def []f32) []f32`: Retrieves a list of f32 with a default.
- `get_list_f64(key string) ![]f64`: Retrieves a list of 64-bit floats.
- `get_list_f64_default(key string, def []f64) []f64`: Retrieves a list of f64 with a default.
- `get_list_i8(key string) ![]i8`: Retrieves a list of 8-bit signed integers.
- `get_list_i8_default(key string, def []i8) []i8`: Retrieves a list of i8 with a default.
- `get_list_i16(key string) ![]i16`: Retrieves a list of 16-bit signed integers.
- `get_list_i16_default(key string, def []i16) []i16`: Retrieves a list of i16 with a default.
- `get_list_i64(key string) ![]i64`: Retrieves a list of 64-bit signed integers.
- `get_list_i64_default(key string, def []i64) []i64`: Retrieves a list of i64 with a default.
- `get_list_u16(key string) ![]u16`: Retrieves a list of 16-bit unsigned integers.
- `get_list_u16_default(key string, def []u16) []u16`: Retrieves a list of u16 with a default.
- `get_list_u32(key string) ![]u32`: Retrieves a list of 32-bit unsigned integers.
- `get_list_u32_default(key string, def []u32) []u32`: Retrieves a list of u32 with a default.
- `get_list_u64(key string) ![]u64`: Retrieves a list of 64-bit unsigned integers.
- `get_list_u64_default(key string, def []u64) []u64`: Retrieves a list of u64 with a default.
- `get_list_namefix(key string) ![]string`: Retrieves a list of strings, normalizing each item (e.g., "My Name" -> "my_name").
- `get_list_namefix_default(key string, def []string) ![]string`: Retrieves a list of name-fixed strings with a default.
### Specialized Retrieval
- `get_map() map[string]string`: Returns all parameters as a map.
- `get_path(key string) !string`: Retrieves a path string.
- `get_path_create(key string) !string`: Retrieves a path string, creating the directory if it doesn't exist.
- `get_from_hashmap(key string, defval string, hashmap map[string]string) !string`: Retrieves a value from a provided hashmap based on the parameter's value.
- `get_storagecapacity_in_bytes(key string) !u64`: Converts storage capacity strings (e.g., "10 GB", "500 MB") to bytes (u64).
- `get_storagecapacity_in_bytes_default(key string, defval u64) !u64`: Retrieves storage capacity in bytes with a default.
- `get_storagecapacity_in_gigabytes(key string) !u64`: Converts storage capacity strings to gigabytes (u64).
- `get_time(key string) !ourtime.OurTime`: Parses a time string (relative or absolute) into an `ourtime.OurTime` object.
- `get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime`: Retrieves time with a default.
- `get_time_interval(key string) !Duration`: Parses a time interval string into a `Duration` object.
- `get_timestamp(key string) !Duration`: Parses a timestamp string into a `Duration` object.
- `get_timestamp_default(key string, defval Duration) !Duration`: Retrieves a timestamp with a default.

View File

@@ -0,0 +1,155 @@
# Pathlib Usage Guide
## Overview
The pathlib module provides a comprehensive interface for handling file system operations. Key features include:
- Robust path handling for files, directories, and symlinks
- Support for both absolute and relative paths
- Automatic home directory expansion (~)
- Recursive directory operations
- Path filtering and listing
- File and directory metadata access
## Basic Usage
### Importing pathlib
```v
import freeflowuniverse.herolib.core.pathlib
```
### Creating Path Objects
This will figure out if the path is a dir, file and if it exists.
```v
// Create a Path object for a file
mut file_path := pathlib.get("path/to/file.txt")
// Create a Path object for a directory
mut dir_path := pathlib.get("path/to/directory")
```
if you know in advance if you expect a dir or file its better to use `pathlib.get_dir(path:...,create:true)` or `pathlib.get_file(path:...,create:true)`.
### Basic Path Operations
```v
// Get absolute path
abs_path := file_path.absolute()
// Get real path (resolves symlinks)
real_path := file_path.realpath()
// Check if path exists
if file_path.exists() {
// Path exists
}
```
## Path Properties and Methods
### Path Types
```v
// Check if path is a file
if file_path.is_file() {
// Handle as file
}
// Check if path is a directory
if dir_path.is_dir() {
// Handle as directory
}
// Check if path is a symlink
if file_path.is_link() {
// Handle as symlink
}
```
### Path Normalization
```v
// Normalize path (remove extra slashes, resolve . and ..)
normalized_path := file_path.path_normalize()
// Get path directory
dir_path := file_path.path_dir()
// Get path name without extension
name_no_ext := file_path.name_no_ext()
```
## File and Directory Operations
### File Operations
```v
// Write to file
file_path.write("Content to write")!
// Read from file
content := file_path.read()!
// Delete file
file_path.delete()!
```
### Directory Operations
```v
// Create directory
mut dir := pathlib.get_dir(
path: "path/to/new/dir"
create: true
)!
// List directory contents
mut dir_list := dir.list()!
// Delete directory
dir.delete()!
```
### Symlink Operations
```v
// Create symlink
file_path.link("path/to/symlink", delete_exists: true)!
// Resolve symlink
real_path := file_path.realpath()
```
## Advanced Operations
### Path Copying
```v
// Copy file to destination
file_path.copy(dest: "path/to/destination")!
```
### Recursive Operations
```v
// List directory recursively
mut recursive_list := dir.list(recursive: true)!
// Delete directory recursively
dir.delete()!
```
### Path Filtering
```v
// List files matching pattern
mut filtered_list := dir.list(
regex: [r".*\.txt$"],
recursive: true
)!
```
## Best Practices
### Error Handling
```v
if file_path.exists() {
// Safe to operate
} else {
// Handle missing file
}
```

View File

@@ -0,0 +1,204 @@
# Redisclient Module
The `redisclient` module in Herolib provides a comprehensive client for interacting with Redis, supporting various commands, caching, queues, and RPC mechanisms.
## Key Features
- **Direct Redis Commands**: Access to a wide range of Redis commands (strings, hashes, lists, keys, etc.).
- **Caching**: Built-in caching mechanism with namespace support and expiration.
- **Queues**: Simple queue implementation using Redis lists.
- **RPC**: Remote Procedure Call (RPC) functionality over Redis queues for inter-service communication.
## Basic Usage
To get a Redis client instance, use `redisclient.core_get()`. By default, it connects to `127.0.0.1:6379`. You can specify a different address and port using the `RedisURL` struct.
```v
import freeflowuniverse.herolib.core.redisclient
// Connect to default Redis instance (127.0.0.1:6379)
mut redis := redisclient.core_get()!
// Or connect to a specific Redis instance
// mut redis_url := redisclient.RedisURL{address: 'my.redis.server', port: 6380}
// mut redis := redisclient.core_get(redis_url)!
// Example: Set and Get a key
redis.set('mykey', 'myvalue')!
value := redis.get('mykey')!
// assert value == 'myvalue'
// Example: Check if a key exists
exists := redis.exists('mykey')!
// assert exists == true
// Example: Delete a key
redis.del('mykey')!
```
## Redis Commands
The `Redis` object provides methods for most standard Redis commands. Here are some examples:
### String Commands
- `set(key string, value string) !`: Sets the string value of a key.
- `get(key string) !string`: Gets the string value of a key.
- `set_ex(key string, value string, ex string) !`: Sets a key with an expiration time in seconds.
- `incr(key string) !int`: Increments the integer value of a key by one.
- `decr(key string) !int`: Decrements the integer value of a key by one.
- `append(key string, value string) !int`: Appends a value to a key.
- `strlen(key string) !int`: Gets the length of the value stored in a key.
```v
redis.set('counter', '10')!
redis.incr('counter')! // counter is now 11
val := redis.get('counter')! // "11"
```
### Hash Commands
- `hset(key string, skey string, value string) !`: Sets the string value of a hash field.
- `hget(key string, skey string) !string`: Gets the value of a hash field.
- `hgetall(key string) !map[string]string`: Gets all fields and values in a hash.
- `hexists(key string, skey string) !bool`: Checks if a hash field exists.
- `hdel(key string, skey string) !int`: Deletes one or more hash fields.
```v
redis.hset('user:1', 'name', 'John Doe')!
redis.hset('user:1', 'email', 'john@example.com')!
user_name := redis.hget('user:1', 'name')! // "John Doe"
user_data := redis.hgetall('user:1')! // map['name':'John Doe', 'email':'john@example.com']
```
### List Commands
- `lpush(key string, element string) !int`: Inserts all specified values at the head of the list stored at key.
- `rpush(key string, element string) !int`: Inserts all specified values at the tail of the list stored at key.
- `lpop(key string) !string`: Removes and returns the first element of the list stored at key.
- `rpop(key string) !string`: Removes and returns the last element of the list stored at key.
- `llen(key string) !int`: Gets the length of a list.
- `lrange(key string, start int, end int) ![]resp.RValue`: Gets a range of elements from a list.
```v
redis.lpush('mylist', 'item1')!
redis.rpush('mylist', 'item2')!
first_item := redis.lpop('mylist')! // "item1"
```
### Set Commands
- `sadd(key string, members []string) !int`: Adds the specified members to the set stored at key.
- `smismember(key string, members []string) ![]int`: Returns if member is a member of the set stored at key.
```v
redis.sadd('myset', ['member1', 'member2'])!
is_member := redis.smismember('myset', ['member1', 'member3'])! // [1, 0]
```
### Key Management
- `keys(pattern string) ![]string`: Finds all keys matching the given pattern.
- `del(key string) !int`: Deletes a key.
- `expire(key string, seconds int) !int`: Sets a key's time to live in seconds.
- `ttl(key string) !int`: Gets the time to live for a key in seconds.
- `flushall() !`: Deletes all the keys of all the existing databases.
- `flushdb() !`: Deletes all the keys of the currently selected database.
- `selectdb(database int) !`: Changes the selected database.
```v
redis.set('temp_key', 'value')!
redis.expire('temp_key', 60)! // Expires in 60 seconds
```
## Redis Cache
The `RedisCache` struct provides a convenient way to implement caching using Redis.
```v
import freeflowuniverse.herolib.core.redisclient
mut redis := redisclient.core_get()!
mut cache := redis.cache('my_app_cache')
// Set a value in cache with expiration (e.g., 3600 seconds)
cache.set('user:profile:123', '{ "name": "Alice" }', 3600)!
// Get a value from cache
cached_data := cache.get('user:profile:123') or {
// Cache miss, fetch from source
println('Cache miss for user:profile:123')
return
}
// println('Cached data: ${cached_data}')
// Check if a key exists in cache
exists := cache.exists('user:profile:123')
// assert exists == true
// Reset the cache for the namespace
cache.reset()!
```
## Redis Queue
The `RedisQueue` struct provides a simple queue mechanism using Redis lists.
```v
import freeflowuniverse.herolib.core.redisclient
import time
mut redis := redisclient.core_get()!
mut my_queue := redis.queue_get('my_task_queue')
// Add items to the queue
my_queue.add('task1')!
my_queue.add('task2')!
// Get an item from the queue with a timeout (e.g., 1000 milliseconds)
task := my_queue.get(1000)!
// assert task == 'task1'
// Pop an item without timeout (returns error if no item)
task2 := my_queue.pop()!
// assert task2 == 'task2'
```
## Redis RPC
The `RedisRpc` struct enables Remote Procedure Call (RPC) over Redis, allowing services to communicate by sending messages to queues and waiting for responses.
```v
import freeflowuniverse.herolib.core.redisclient
import json
import time
mut redis := redisclient.core_get()!
mut rpc_client := redis.rpc_get('my_rpc_service')
// Define a function to process RPC requests (server-side)
fn my_rpc_processor(cmd string, data string) !string {
// Simulate some processing based on cmd and data
return 'Processed: cmd=${cmd}, data=${data}'
}
// --- Client Side (calling the RPC) ---
// Call the RPC service
response := rpc_client.call(
cmd: 'greet',
data: '{"name": "World"}',
wait: true,
timeout: 5000 // 5 seconds timeout
)!
// println('RPC Response: ${response}')
// assert response == 'Processed: cmd=greet, data={"name": "World"}'
// --- Server Side (processing RPC requests) ---
// In a separate goroutine or process, you would run:
// rpc_client.process(my_rpc_processor, timeout: 0)! // timeout 0 means no timeout, keeps processing
// Example of how to process a single request (for testing/demonstration)
// In a real application, this would be in a loop or a background worker
// return_queue_name := rpc_client.process(my_rpc_processor, timeout: 1000)!
// result := rpc_client.result(1000, return_queue_name)!
// println('Processed result: ${result}')

View File

@@ -0,0 +1,99 @@
# TextTools Module
The `texttools` module provides a comprehensive set of utilities for text manipulation and processing.
## Functions and Examples:
```v
import freeflowuniverse.herolib.core.texttools
assert hello_world == texttools.name_fix("Hello World!")
```
### Name/Path Processing
* `name_fix(name string) string`: Normalizes filenames and paths.
* `name_fix_keepspace(name string) !string`: Like name_fix but preserves spaces.
* `name_fix_no_ext(name_ string) string`: Removes file extension.
* `name_fix_snake_to_pascal(name string) string`: Converts snake_case to PascalCase.
```v
name := texttools.name_fix_snake_to_pascal("hello_world") // Result: "HelloWorld"
```
* `snake_case(name string) string`: Converts PascalCase to snake_case.
```v
name := texttools.snake_case("HelloWorld") // Result: "hello_world"
```
* `name_split(name string) !(string, string)`: Splits name into site and page components.
### Text Cleaning
* `name_clean(r string) string`: Normalizes names by removing special characters.
```v
name := texttools.name_clean("Hello@World!") // Result: "HelloWorld"
```
* `ascii_clean(r string) string`: Removes all non-ASCII characters.
* `remove_empty_lines(text string) string`: Removes empty lines from text.
```v
text := texttools.remove_empty_lines("line1\n\nline2\n\n\nline3") // Result: "line1\nline2\nline3"
```
* `remove_double_lines(text string) string`: Removes consecutive empty lines.
* `remove_empty_js_blocks(text string) string`: Removes empty code blocks (```...```).
### Command Line Parsing
* `cmd_line_args_parser(text string) ![]string`: Parses command line arguments with support for quotes and escaping.
```v
args := texttools.cmd_line_args_parser("'arg with spaces' --flag=value") // Result: ['arg with spaces', '--flag=value']
```
* `text_remove_quotes(text string) string`: Removes quoted sections from text.
* `check_exists_outside_quotes(text string, items []string) bool`: Checks if items exist in text outside of quotes.
### Text Expansion
* `expand(txt_ string, l int, expand_with string) string`: Expands text to a specified length with a given character.
### Indentation
* `indent(text string, prefix string) string`: Adds indentation prefix to each line.
```v
text := texttools.indent("line1\nline2", " ") // Result: " line1\n line2\n"
```
* `dedent(text string) string`: Removes common leading whitespace from every line.
```v
text := texttools.dedent(" line1\n line2") // Result: "line1\nline2"
```
### String Validation
* `is_int(text string) bool`: Checks if text contains only digits.
* `is_upper_text(text string) bool`: Checks if text contains only uppercase letters.
### Multiline Processing
* `multiline_to_single(text string) !string`: Converts multiline text to a single line with proper escaping.
### Text Splitting
* `split_smart(t string, delimiter_ string) []string`: Intelligent string splitting that respects quotes.
### Tokenization
* `tokenize(text_ string) TokenizerResult`: Tokenizes text into meaningful parts.
* `text_token_replace(text string, tofind string, replacewith string) !string`: Replaces tokens in text.
### Version Parsing
* `version(text_ string) int`: Converts version strings to comparable integers.
```v
ver := texttools.version("v0.4.36") // Result: 4036
ver = texttools.version("v1.4.36") // Result: 1004036
```
### Formatting
* `format_rfc1123(t time.Time) string`: Formats a time.Time object into RFC 1123 format.
### Array Operations
* `to_array(r string) []string`: Converts a comma or newline separated list to an array of strings.
```v
text := "item1,item2,item3"
array := texttools.to_array(text) // Result: ['item1', 'item2', 'item3']
```
* `to_array_int(r string) []int`: Converts a text list to an array of integers.
* `to_map(mapstring string, line string, delimiter_ string) map[string]string`: Intelligent mapping of a line to a map based on a template.
```v
r := texttools.to_map("name,-,-,-,-,pid,-,-,-,-,path",
"root 304 0.0 0.0 408185328 1360 ?? S 16Dec23 0:34.06 /usr/sbin/distnoted")
// Result: {'name': 'root', 'pid': '1360', 'path': '/usr/sbin/distnoted'}
```

View File

@@ -4,7 +4,7 @@ has mechanisms to print better to console, see the methods below
import as
```vlang
```v
import freeflowuniverse.herolib.ui.console
```

View File

@@ -2,14 +2,11 @@
this is how we want example scripts to be, see the first line
```vlang
#!/usr/bin/env -S v -gc none -cc tcc -d use_openssl -enable-globals run
```v
#!/usr/bin/env -S v -cg -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
import freeflowuniverse.herolib...
mut ds := daguserver.get()!
println(ds)
```
the files are in ~/code/github/freeflowuniverse/herolib/examples for herolib
@@ -17,3 +14,5 @@ the files are in ~/code/github/freeflowuniverse/herolib/examples for herolib
## important instructions
- never use fn main() in a .vsh script
- always use the top line as in example above
- these scripts can be executed as is but can also use vrun $pathOfFile

View File

@@ -0,0 +1,165 @@
V allows for easily using text templates, expanded at compile time to
V functions, that efficiently produce text output. This is especially
useful for templated HTML views, but the mechanism is general enough
to be used for other kinds of text output also.
# Template directives
Each template directive begins with an `@` sign.
Some directives contain a `{}` block, others only have `''` (string) parameters.
Newlines on the beginning and end are ignored in `{}` blocks,
otherwise this (see [if](#if) for this syntax):
```html
@if bool_val {
<span>This is shown if bool_val is true</span>
}
```
... would output:
```html
<span>This is shown if bool_val is true</span>
```
... which is less readable.
## if
The if directive, consists of three parts, the `@if` tag, the condition (same syntax like in V)
and the `{}` block, where you can write html, which will be rendered if the condition is true:
```
@if <condition> {}
```
### Example
```html
@if bool_val {
<span>This is shown if bool_val is true</span>
}
```
One-liner:
```html
@if bool_val { <span>This is shown if bool_val is true</span> }
```
The first example would result in:
```html
<span>This is shown if bool_val is true</span>
```
... while the one-liner results in:
```html
<span>This is shown if bool_val is true</span>
```
## for
The for directive consists of three parts, the `@for` tag,
the condition (same syntax like in V) and the `{}` block,
where you can write text, rendered for each iteration of the loop:
```
@for <condition> {}
```
### Example for @for
```html
@for i, val in my_vals {
<span>$i - $val</span>
}
```
One-liner:
```html
@for i, val in my_vals { <span>$i - $val</span> }
```
The first example would result in:
```html
<span>0 - "First"</span>
<span>1 - "Second"</span>
<span>2 - "Third"</span>
...
```
... while the one-liner results in:
```html
<span>0 - "First"</span>
<span>1 - "Second"</span>
<span>2 - "Third"</span>
...
```
You can also write (and all other for condition syntaxes that are allowed in V):
```html
@for i = 0; i < 5; i++ {
<span>$i</span>
}
```
## include
The include directive is for including other html files (which will be processed as well)
and consists of two parts, the `@include` tag and a following `'<path>'` string.
The path parameter is relative to the template file being called.
### Example for the folder structure of a project using templates:
```
Project root
/templates
- index.html
/headers
- base.html
```
`index.html`
```html
<div>@include 'header/base'</div>
```
> Note that there shouldn't be a file suffix,
> it is automatically appended and only allows `html` files.
## js
The js directive consists of two parts, the `@js` tag and `'<path>'` string,
where you can insert your src
```
@js '<url>'
```
### Example for the @js directive:
```html
@js 'myscripts.js'
```
# Variables
All variables, which are declared before the $tmpl can be used through the `@{my_var}` syntax.
It's also possible to use properties of structs here like `@{my_struct.prop}`.
# Escaping
The `@` symbol starts a template directive. If you need to use `@` as a regular
character within a template, escape it by using a double `@` like this: `@@`.

View File

@@ -11,45 +11,22 @@
when I generate vlang scripts I will always use .vsh extension and use following as first line:
```
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
```
- a .vsh is a v shell script and can be executed as is, no need to use v ...
- in .vsh file there is no need for a main() function
- these scripts can be used for examples or instruction scripts e.g. an installs script
## to do argument parsing use following examples
## executing vlang scripts
```v
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import os
import flag
mut fp := flag.new_flag_parser(os.args)
fp.application('compile.vsh')
fp.version('v0.1.0')
fp.description('Compile hero binary in debug or production mode')
fp.skip_executable()
prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested {
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
}
As AI agent I should also execute v or .vsh scripts with vrun
```bash
vrun ~/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel.vsh
```
## when creating a test script
## executing test scripts
instruct user to test as follows (vtest is an alias which gets installed when herolib gets installed), can be done for a dir and for a file
@@ -58,3 +35,4 @@ vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
```
- use ~ so it works over all machines
- don't use 'v test', we have vtest as alternative

View File

@@ -1 +0,0 @@
../lib/core/httpconnection/readme.md

View File

@@ -0,0 +1,52 @@
params:
- filepath: /Users/despiegk/code/github/freeflowuniverse/herolib/lib/clients/openai
make a dense overview of the code above, easy to understand for AI
the result is 1 markdown file called codeoverview.md and is stored in $filepath
try to figure out which functions are more important and which are less important, so that the most important functions are at the top of section you are working on
the template is as follows
```md
# the name of the module
2-5 liner description
## factory
is there factory, which one and quick example how to call, dont say in which file not relevant
show how to import the module is as follows: import freeflowuniverse.herolib.
and then starting from lib e.g. lib/clients/mycelium would result in import freeflowuniverse.herolib. clients.mycelium
## overview
quick overview as list with identations, of the structs and its methods
## structs
### structname
now list the methods & arguments, for arguments use table
for each method show the arguments needed to call the method, and what it returns
### methods
- if any methods which are on module
- only show public methods, don't show the get/set/exists methods on module level as part of factory.
```
don't mention what we don't show because of rules above.
the only output we want is markdown file as follows
===WRITE===
$filepath
===CONTENT===
$the content of the generated markdown file
===END===

View File

@@ -0,0 +1,22 @@
remove all navigation elements, and index
for each method, move the args as used in the methods to the method section so its easier to read
start of output file is:
# the name of the module
2-5 liner description
## factory
is there factory, which one and quick example how to call, dont say in which file not relevant
show how to import the module is as follows: import freeflowuniverse.herolib.
and then starting from lib e.g. lib/clients/mycelium would result in import freeflowuniverse.herolib. clients.mycelium
## structs and methods
quick overview as list with identations, of the structs and its methods
ONLY OUTPUT THE MARKDOWN FILE, NOTHING ELSE

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
in hero.db
make a generic function which takes any of the root objects (which inherits from Base)
and gets a json from it and add a save() function to it to store it in postgresql (see postgresql client)
and also a get and deserializes
the json is put in table as follows
tablename: $dirname_$rootobjectname all lowercase
each table has
- id
- ... the fields which represents indexes (see @[index])
- data which is the json
information how to use generics see aiprompts/v_advanced/generics.md and aiprompts/v_advanced/reflection.md

View File

@@ -0,0 +1,45 @@
$NAME = calendar
walk over all models from biz: db/heromodels/src/models/$NAME in the rust repo
create nice structured public models in Vlang (V) see instructions in herlolib
put the results in /Users/despiegk/code/github/freeflowuniverse/herolib/lib/hero/models/$NAME
put decorator on fields which need to be indexed: use @[index] for that at end of line of the property of the struct
copy the documentation as well and put on the vstruct and on its fields
make instructions so a coding agent can execute it, put the models in files, ...
keep it all simple
don't do anything additional for modules, don't do import
at top of each file we have ```module $NAME```
make sure all time related fields are in u64 format, use unix timestamp for that
don't create management classes, only output the structs, don't create a mod.v, don't make .v scripts executatble, don't create a main.v
## now also make sure we use core.base as follows
```
import freeflowuniverse.herolib.hero.models.core
// Account represents a financial account for tracking balances and transactions
// Supports multiple account types (checking, savings, investment, etc.)
pub struct Account {
core.Base
```
remove Local BaseModel
make sure module ... is always at first line of file
- remove id from the model we update because it is in the Base
- created_at u64 // Creation timestamp
- updated_at u64 // Last modification timestamp
- basically each property in the Base should be removed from the model

View File

@@ -0,0 +1 @@
Kimi k2 on groq is doing well

View File

@@ -0,0 +1,20 @@
in lib/hero/models
for governance and legal
make sure we use core.base as follows
import freeflowuniverse.herolib.hero.models.core
// Account represents a financial account for tracking balances and transactions
// Supports multiple account types (checking, savings, investment, etc.)
pub struct Account {
core.Base
remove Local BaseModel
make sure module ... is always at first line of file
- remove id from the model we update because it is in the Base
- created_at u64 // Creation timestamp
- updated_at u64 // Last modification timestamp
- basically each property in the Base should be removed from the model

View File

@@ -0,0 +1,109 @@
## INTENT
we use heroscript to communicate actions and events in a structured format.
we want you to parse user intents and generate the corresponding heroscript.
ONLY RETURN THE HEROSCRIPT STATEMENTS, can be more than 1
## HEROSCRIPT FORMAT
HeroScript is a concise scripting language with the following structure:
```heroscript
!!actor.action_name
param1: 'value1'
param2: 'value with spaces'
multiline_description: '
This is a multiline description.
It can span multiple lines.
'
arg1 arg2 // Arguments without keys
!!actor.action_name2 param1:something param2:'something with spaces' nr:3
```
Key characteristics:
- **Actions**: Start with `!!`, followed by `actor.action_name` (e.g., `!!mailclient.configure`).
- **Parameters**: Defined as `key:value`. Values can be quoted for spaces.
- **Multiline Support**: Parameters like `description` can span multiple lines.
- **Arguments**: Values without keys (e.g., `arg1`).
- params can be on 1 line, with spaces in between
- time can be as +1h, +1d, +1w (hour, day, week), ofcourse 1 can be any number, +1 means 1 hour from now
- time format is: dd/mm/yyyy hh:mm (ONLY USE THIS)
- comma separation is used a lot in arguments e.g. 'jan,kristof' or 'jan , kristof' remove spaces, is list of 2
- note only !! is at start of line, rest has spaces per instruction
- make one empty line between 1 heroscript statements
- everything after // is comment
## HEROSCRIPT SCHEMA
the language we understand
### calendar management
```heroscript
!!calendar.create when:'+1h' descr:'this is event to discuss eng' attendees:'jan,kristof' name:'meet1' tags:'eng,urgent'
!!calendar.delete name:'meet1'
!!calendar.list tags:'urgent'
```
### contact management
```heroscript
!!contact.add name:'jan' email:'jan@example.com' phone:'123-456-7890'
!!contact.remove name:'jan'
!!contact.list
```
### task management
```heroscript
!!task.create title:'Prepare presentation' due:'+1d' assignee:'jan' name:'task1' tags:'eng,urgent'
deadline:'+10d' duration:'1h'
!!task.update name:'task1' status:'in progress'
!!task.delete name:'task1'
!!task.list
```
### project management
```heroscript
!!project.create title:'Cloud Product Development' description:'Track progress of cloud product development' name:'cloud_prod'
!!project.update name:'cloud_prod' status:'in progress'
!!project.delete name:'cloud_prod'
!!project.list
!!project.tasks_list name:'cloud_prod' //required properties are name, description, and assignee of not given ask
!!project.tasks_add names:'task1, task2'
!!project.tasks_remove names:'task1, task2'
```
### SUPPORTED TAGS
only tags supported are:
- for intent: eng, prod, support, mgmt, marketing
- for urgency: urgent, high, medium, low
### generic remarks
- names are lowercase and snake_case, can be distilled out of title if only title given, often a user will say name but that means title
- time: format of returned data or time is always dd/mm/yyyy hh:min
## IMPORTANT STARTING INFO
- current time is 10/08/2025 05:10 , use this to define any time-related parameters
## USER INTENT
I want a meeting tomorrow 10am, where we will discuss our new product for the cloud with jan and alex, and the urgency is high
also let me know which other meetings I have which are urgent
can you make a project where we can track the progress of our new product development? Name is 'Cloud Product Development'
Please add tasks to the project in line to creating specifications, design documents, and implementation plans.

View File

@@ -0,0 +1,64 @@
SYSTEM
You are a HeroScript compiler. Convert user intents into valid HeroScript statements.
OUTPUT RULES
1) Return ONLY HeroScript statements. No prose, no backticks.
2) Separate each statement with exactly ONE blank line.
3) Keys use snake_case. Names are lowercase snake_case derived from titles (non-alnum → "_", collapse repeats, trim).
4) Lists are comma-separated with NO spaces (e.g., "jan,alex").
5) Times: OUTPUT MUST BE ABSOLUTE in "dd/mm/yyyy hh:mm" (Europe/Zurich). Convert relative times (e.g., "tomorrow 10am") using CURRENT_TIME.
6) Tags: include at most one intent tag and at most one urgency tag when present.
- intent: eng,prod,support,mgmt,marketing
- urgency: urgent,high,medium,low
7) Quotes: quote values containing spaces; otherwise omit quotes (allowed either way).
8) Comments only with // if the user explicitly asks for explanations; otherwise omit.
SCHEMA (exact actions & parameters)
!!calendar.create when:'dd/mm/yyyy hh:mm' name:'<name>' descr:'<text>' attendees:'a,b,c' tags:'intent,urgency'
!!calendar.delete name:'<name>'
!!calendar.list [tags:'tag1,tag2']
!!contact.add name:'<name>' email:'<email>' phone:'<phone>'
!!contact.remove name:'<name>'
!!contact.list
!!task.create title:'<title>' name:'<name>' [due:'dd/mm/yyyy hh:mm'] [assignee:'<name>'] [tags:'intent,urgency'] [deadline:'dd/mm/yyyy hh:mm'] [duration:'<Nd Nh Nm> or <Nh>']
!!task.update name:'<name>' [status:'in progress|done|blocked|todo']
!!task.delete name:'<name>'
!!task.list
!!project.create title:'<title>' description:'<text>' name:'<name>'
!!project.update name:'<name>' [status:'in progress|done|blocked|todo']
!!project.delete name:'<name>'
!!project.list
!!project.tasks_list name:'<project_name>'
!!project.tasks_add name:'<project_name>' names:'task_a,task_b'
!!project.tasks_remove name:'<project_name>' names:'task_a,task_b'
NORMALIZATION & INFERENCE (silent)
- Derive names from titles when missing (see rule 3). Ensure consistency across statements.
- Map phrases to tags when obvious (e.g., "new product" ⇒ intent: prod; "high priority" ⇒ urgency: high).
- Attendees: split on commas, trim, lowercase given names.
- If the user asks for “urgent meetings,” use tags:'urgent' specifically.
- Prefer concise descriptions pulled from the users phrasing.
- Name's are required, if missing ask for clarification.
- For calendar management, ensure to include all relevant details such as time, attendees, and description.
CURRENT_TIME
10/08/2025 05:10
USER_MESSAGE
I want a meeting tomorrow 10am, where we will discuss our new product for the cloud with jan and alex, and the urgency is high
also let me know which other meetings I have which are urgent
can you make a project where we can track the progress of our new product development? Name is 'Cloud Product Development'
Please add tasks to the project in line to creating specifications, design documents, and implementation plans.
END

View File

@@ -0,0 +1,82 @@
## INSTRUCTIONS
the user will send me multiple instructions what they wants to do, I want you to put them in separate categories
The categories we have defined are:
- calendar management
- schedule meetings, events, reminders
- list these events
- delete them
- contact management
- add/remove contact information e.g. phone numbers, email addresses, address information
- list contacts, search
- task or project management
- anything we need to do, anything we need to track and plan
- create/update tasks, set deadlines
- mark tasks as complete
- delete tasks
- project management
- communication (chat, email)
- see what needs to be communicate e.g. send a chat to ...
- search statements
- find on internet, find specific information from my friends
I want you to detect the intent and make multiple blocks out of the intent, each block should correspond to one of the identified intents, identify the intent with name of the category eg. calendar, only use above names
what user wants to do, stay as close as possible to the original instructions, copy the exact instructions as where given by the user, we only need to sort the instructions in these blocks
for each instruction make a separate block, e.g. if 2 tasks are given, create 2 blocks
the format to return is: (note newline after each title of block)
```template
===CALENDAR===\n
$the copied text from what user wants
===CONTACT===\n
...
===QUESTION===\n
put here what our system needs to ask to the user anything which is not clear
===END===\n
```
I want you to execute above on instructions as given by user below, give text back ONLY supporting the template
note for format is only ===$NAME=== and then on next lines the original instructions from the user, don't change
## special processing of info
- if a date or time specified e.g. tomorrow, time, ... calculate back from current date
## IMPORTANT STARTING INFO
- current time is 10/08/2025 05:10 (format of returned data is always dd/mm/yyyy hh:min)
- use the current time to define formatted time out of instructions
- only return the formatted time
## UNCLEAR INFO
check in instructions e.g. things specified like you, me, ...
are not clear ask specifically who do you mean
if task, specify per task, who needs to do it and when, make sure each instruction (block) is complete and clear for further processing
be very specific with the questions e.g. who is you, ...
## EXECUTE ABOVE ON THE FOLLOWING
I am planning a birthday for my daughters tomorrow, there will be 10 people.
I would like to know if you can help me with the preparations.
I need a place for my daughter's birthday party.
I need to send message to my wife isabelle that she needs to pick up the cake.

View File

@@ -0,0 +1,16 @@
import json
from jinja2 import Template
# load OpenRPC spec
with open("openrpc.json") as f:
spec = json.load(f)
# load template
with open("openrpc_to_md.j2") as f:
tmpl = Template(f.read())
# render markdown
output = tmpl.render(spec=spec)
print(output)

View File

@@ -0,0 +1,163 @@
import re
import yaml
import json
import requests
from collections import defaultdict
from jsonschema import validate, Draft7Validator
# --- Load OpenRPC meta-schema ---
def load_openrpc_schema():
url = "https://open-rpc.github.io/meta-schema.json"
resp = requests.get(url)
resp.raise_for_status()
return resp.json()
OPENRPC_SCHEMA = load_openrpc_schema()
def parse_dense_markdown(md_text: str):
methods = []
schemas = {}
# Split into sections
sections = re.split(r"^# ", md_text, flags=re.M)
secmap = {}
for sec in sections:
if not sec.strip():
continue
title, _, body = sec.partition("\n")
secmap[title.strip()] = body.strip()
# --- Methods ---
if "Methods" in secmap:
method_blocks = re.split(r"^## ", secmap["Methods"], flags=re.M)
for block in method_blocks:
if not block.strip():
continue
name, _, body = block.partition("\n")
method = {"name": name.strip(), "params": [], "result": {}}
lines = [l.rstrip() for l in body.splitlines() if l.strip()]
# description before **Params**
desc_lines = []
i = 0
while i < len(lines) and not lines[i].startswith("**Params**"):
desc_lines.append(lines[i])
i += 1
method["description"] = " ".join(desc_lines).strip()
# Params
if "**Params**" in lines:
pi = lines.index("**Params**") + 1
while pi < len(lines) and not lines[pi].startswith("**Result**"):
line = lines[pi].lstrip("-").strip()
if line and not line.lower().startswith("none"):
pname, _, pdesc = line.partition("(")
pname = pname.strip()
ptype = pdesc.split(",")[0].replace(")", "").strip() if pdesc else "object"
required = "required" in line
param = {
"name": pname,
"required": required,
"schema": {"type": map_type(ptype)}
}
method["params"].append(param)
pi += 1
# Result
if "**Result**" in lines:
ri = lines.index("**Result**") + 1
if ri < len(lines):
rline = lines[ri].lstrip("-").strip()
rname, _, rtype = rline.partition(":")
rname = rname.strip()
rtype = rtype.strip()
schema = parse_result_type(rtype)
method["result"] = {"name": rname, "schema": schema}
methods.append(method)
# --- Schemas ---
if "Schemas" in secmap:
schema_blocks = re.split(r"^## ", secmap["Schemas"], flags=re.M)
for block in schema_blocks:
if not block.strip():
continue
name, _, body = block.partition("\n")
lines = body.splitlines()
code_block = []
req_fields = []
in_yaml = False
for l in lines:
if l.strip().startswith("```yaml"):
in_yaml = True
continue
elif l.strip().startswith("```"):
in_yaml = False
continue
if in_yaml:
code_block.append(l)
if l.strip().startswith("*Required:"):
req_fields = [x.strip() for x in l.split(":")[1].split(",")]
if code_block:
schema_def = yaml.safe_load("\n".join(code_block))
props = {}
for fname, ftype in schema_def.items():
if isinstance(ftype, str):
base = ftype.split("#")[0].strip()
desc = ftype.split("#")[1].strip() if "#" in ftype else None
props[fname] = {"type": map_type(base)}
if desc:
props[fname]["description"] = desc
schemas[name.strip()] = {
"type": "object",
"properties": props,
"required": req_fields
}
spec = {"openrpc": "1.0.0", "methods": methods, "components": {"schemas": schemas}}
# --- Validate against OpenRPC schema ---
validator = Draft7Validator(OPENRPC_SCHEMA)
errors = sorted(validator.iter_errors(spec), key=lambda e: e.path)
if errors:
for err in errors:
print(f"❌ Validation error at {list(err.path)}: {err.message}")
raise ValueError("Generated spec is not valid OpenRPC")
else:
print("✅ Spec is valid OpenRPC")
return spec
# --- Helpers ---
def map_type(t):
mapping = {"int": "integer", "str": "string", "bool": "boolean", "object": "object"}
return mapping.get(t, t)
def parse_result_type(rtype):
if "|" in rtype:
oneofs = []
for variant in rtype.split("|"):
v = variant.strip()
if v.startswith("[") and v.endswith("]"):
oneofs.append({"type": "array", "items": {"$ref": f"#/components/schemas/{v[1:-1]}"}})
else:
oneofs.append({"$ref": f"#/components/schemas/{v}"})
return {"oneOf": oneofs}
elif rtype.startswith("[") and rtype.endswith("]"):
return {"type": "array", "items": {"type": map_type(rtype[1:-1])}}
elif rtype in ["int", "str", "bool", "object"]:
return {"type": map_type(rtype)}
else:
return {"$ref": f"#/components/schemas/{rtype}"}
# --- Example usage ---
if __name__ == "__main__":
with open("dense.md") as f:
md = f.read()
spec = parse_dense_markdown(md)
with open("openrpc.json", "w") as f:
json.dump(spec, f, indent=2)

View File

@@ -0,0 +1 @@
pip install jsonschema requests

View File

@@ -0,0 +1,155 @@
# Instructions: Converting OpenRPC → Markdown Shorthand
## Purpose
Transform an OpenRPC specification (JSON or YAML) into a **dense Markdown format** that is:
* Human-readable
* AI-parseable
* Compact (minimal boilerplate)
* Faithful to the original semantics
---
## General Rules
1. **Drop metadata**
Ignore `info`, `servers`, and other metadata not relevant to API usage.
2. **Two main sections**
* `# Methods`
* `# Schemas`
3. **Method representation**
Each method gets its own `## {method_name}` block:
* First line: *description* (if present).
* **Params** section:
* List each parameter as `- name: TYPE (required?)`
* Inline object properties using nested bullet lists or YAML block if complex.
* **Result** section:
* Same style as params.
* Use shorthand for references:
* `$ref: "#/components/schemas/Comment"``Comment`
* Array of refs → `[Comment]`
4. **Schema representation**
Each schema gets its own `## {SchemaName}` block:
* Use fenced YAML block for properties:
```yaml
field: TYPE # description
```
* List required fields below the block:
`*Required: field1, field2*`
---
## Type Conventions
* `type: integer` → `int`
* `type: string` → `str`
* `type: boolean` → `bool`
* `type: object` → `object`
* `type: array` → `[TYPE]` (if items defined)
* `oneOf: [SchemaA, SchemaB]` → `SchemaA | SchemaB`
---
## Handling Complex Types
1. **Objects inside parameters or results**
* If small (≤3 fields), inline as `{ field1: TYPE, field2: TYPE }`.
* If large, expand as YAML block.
Example:
```markdown
- args (object, required)
- id: int
- parent: int
```
2. **Nested schemas (structs in structs)**
* Inline only the top level, reference nested schemas by name.
* If the nested schema is not declared in `components/schemas`, define it under `# Schemas`.
Example:
```markdown
## user_create
**Params**
- user: UserProfile (struct defined below)
```
3. **Arrays**
* `[TYPE]` for primitives (e.g., `[int]`).
* `[SchemaName]` for objects.
4. **Results with multiple options**
* Use `SchemaA | [SchemaA]` for "oneOf".
---
## Example Conversion
OpenRPC (fragment):
```json
{
"name": "comment_get",
"description": "Retrieve comments",
"params": [
{
"name": "args",
"required": true,
"schema": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"author": { "type": "integer" }
}
}
}
],
"result": {
"name": "comments",
"schema": {
"oneOf": [
{ "$ref": "#/components/schemas/Comment" },
{ "type": "array", "items": { "$ref": "#/components/schemas/Comment" } }
]
}
}
}
```
Markdown:
```markdown
## comment_get
Retrieve comments
**Params**
- args (object, required)
- id: int
- author: int
**Result**
- comments: Comment | [Comment]
```
---
This way, any AI (or human) can deterministically map **OpenRPC → Markdown shorthand**.

View File

@@ -0,0 +1,53 @@
import json
import sys
from dense_md_to_openrpc import parse_dense_markdown
from jinja2 import Template
# Load the Jinja2 template for JSON → Markdown
with open("openrpc_to_md.j2") as f:
md_template = Template(f.read())
def roundtrip(md_path: str):
print(f"🔄 Round-trip test for {md_path}")
# 1. Markdown → JSON
with open(md_path) as f:
md_text = f.read()
spec1 = parse_dense_markdown(md_text)
print("✅ Step 1: Markdown → JSON")
# 2. Validate already happens inside parse_dense_markdown
# 3. JSON → Markdown
md2 = md_template.render(spec=spec1)
print("✅ Step 2: JSON → Markdown")
# 4. Markdown → JSON again
spec2 = parse_dense_markdown(md2)
print("✅ Step 3: Markdown → JSON (again)")
# 5. Compare results
spec1_str = json.dumps(spec1, sort_keys=True, indent=2)
spec2_str = json.dumps(spec2, sort_keys=True, indent=2)
if spec1_str == spec2_str:
print("🎉 Round-trip is stable! (JSON1 == JSON2)")
else:
print("⚠️ Round-trip mismatch!")
with open("spec1.json", "w") as f:
f.write(spec1_str)
with open("spec2.json", "w") as f:
f.write(spec2_str)
with open("roundtrip_diff.md", "w") as f:
f.write("## Original JSON (Markdown → JSON)\n```json\n")
f.write(spec1_str + "\n```\n")
f.write("\n## After Round-trip (JSON → Markdown → JSON)\n```json\n")
f.write(spec2_str + "\n```\n")
print("👉 Differences written to spec1.json, spec2.json, and roundtrip_diff.md")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python roundtrip_test.py dense.md")
sys.exit(1)
roundtrip(sys.argv[1])

View File

@@ -0,0 +1,56 @@
# Methods
{% for method in spec.methods %}
## {{ method.name }}
{{ method.description or "" }}
**Params**
{% if method.params|length == 0 %}
- none
{% else %}
{% for p in method.params %}
- {{ p.name }} ({{ p.schema.type or "object" }}{% if p.required %}, required{% endif %})
{% if p.schema.properties %}
{% for field, fdef in p.schema.properties.items() %}
- {{ field }}: {{ fdef.type or "object" }}{% if fdef.description %} — {{ fdef.description }}{% endif %}
{% endfor %}
{% endif %}
{% if p.schema["$ref"] %}
- {{ p.schema["$ref"].split("/")[-1] }}
{% endif %}
{% endfor %}
{% endif %}
**Result**
- {{ method.result.name }}:
{% if method.result.schema.oneOf %}
{% for variant in method.result.schema.oneOf %}
{% if variant["$ref"] %}
- {{ variant["$ref"].split("/")[-1] }}
{% elif variant.type == "array" %}
- [{{ variant.items["$ref"].split("/")[-1] }}]
{% else %}
- {{ variant.type }}
{% endif %}
{% endfor %}
{% elif method.result.schema["$ref"] %}
{{ method.result.schema["$ref"].split("/")[-1] }}
{% elif method.result.schema.type == "array" %}
[{{ method.result.schema.items.type or method.result.schema.items["$ref"].split("/")[-1] }}]
{% elif method.result.schema.type %}
{{ method.result.schema.type }}
{% else %}
object
{% endif %}
---
{% endfor %}
# Schemas
{% for name, schema in spec.components.schemas.items() %}
## {{ name }}
```yaml
{% for field, fdef in schema.properties.items() %}
{{ field }}: {{ fdef.type or "object" }}{% if fdef.description %} # {{ fdef.description }}{% endif %}
{% endfor %}

View File

@@ -1 +0,0 @@
../lib/osal/readme.md

View File

@@ -1 +0,0 @@
../lib/data/ourdb/README.md

View File

@@ -1 +0,0 @@
../lib/data/ourtime/readme.md

View File

@@ -1 +0,0 @@
../lib/data/paramsparser/readme.md

View File

@@ -1,78 +0,0 @@
# HeroScript
## Overview
HeroScript is a simple, declarative scripting language designed to define workflows and execute commands in a structured manner. It follows a straightforward syntax where each action is prefixed with `!!`, indicating the actor and action name.
## Example
A basic HeroScript script for virtual machine management looks like this:
```heroscript
!!vm.define name:'test_vm' cpu:4
memory: '8GB'
storage: '100GB'
description: '
A virtual machine configuration
with specific resources.
'
!!vm.start name:'test_vm'
!!vm.disk_add
name: 'test_vm'
size: '50GB'
type: 'SSD'
!!vm.delete
name: 'test_vm'
force: true
```
### Key Features
- Every action starts with `!!`.
- The first part after `!!` is the actor (e.g., `vm`).
- The second part is the action name (e.g., `define`, `start`, `delete`).
- Multi-line values are supported (e.g., the `description` field).
- Lists are comma-separated where applicable and inside ''.
- If items one 1 line, then no space between name & argument e.g. name:'test_vm'
## Parsing HeroScript
Internally, HeroScript gets parsed into an action object with parameters. Each parameter follows a `key: value` format.
### Parsing Example
```heroscript
!!actor.action
id:a1 name6:aaaaa
name:'need to do something 1'
description:
'
## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
name2: test
name3: hi
name10:'this is with space' name11:aaa11
name4: 'aaa'
//somecomment
name5: 'aab'
```
### Parsing Details
- Each parameter follows a `key: value` format.
- Multi-line values (such as descriptions) support Markdown formatting.
- Comments can be added using `//`.
- Keys and values can have spaces, and values can be enclosed in single quotes.

View File

@@ -1,267 +0,0 @@
## how to process heroscript in Vlang
- heroscript can be converted to a struct,
- the methods available to get the params are in 'params' section further in this doc
```vlang
fn test_play_dagu() ! {
mut plbook := playbook.new(text: thetext_from_above)!
play_dagu(mut plbook)! //see below in vlang block there it all happens
}
pub fn play_dagu(mut plbook playbook.PlayBook) ! {
//find all actions are !!$actor.$actionname. in this case above the actor is !!dagu, we check with the fitler if it exists, if not we return
dagu_actions := plbook.find(filter: 'dagu.')!
if dagu_actions.len == 0 {
return
}
play_dagu_basic(mut plbook)!
}
pub struct DaguScript {
pub mut:
name string
homedir string
title string
reset bool
start bool
colors []string
}
// play_dagu plays the dagu play commands
pub fn play_dagu_basic(mut plbook playbook.PlayBook) ! {
//now find the specific ones for dagu.script_define
mut actions := plbook.find(filter: 'dagu.script_define')!
if actions.len > 0 {
for myaction in actions {
mut p := myaction.params //get the params object from the action object, this can then be processed using the param getters
mut obj := DaguScript{
//INFO: all details about the get methods can be found in 'params get methods' section
name : p.get('name')! //will give error if not exist
homedir : p.get('homedir')!
title : p.get_default('title', 'My Hero DAG')! //uses a default if not set
reset : p.get_default_false('reset')
start : p.get_default_true('start')
colors : p.get_list('colors')
description : p.get_default('description','')!
}
...
}
}
//there can be more actions which will have other filter
}
```
## params get methods (param getters)
```vlang
fn (params &Params) exists(key_ string) bool
//check if arg exist (arg is just a value in the string e.g. red, not value:something)
fn (params &Params) exists_arg(key_ string) bool
//see if the kwarg with the key exists if yes return as string trimmed
fn (params &Params) get(key_ string) !string
//return the arg with nr, 0 is the first
fn (params &Params) get_arg(nr int) !string
//return arg, if the nr is larger than amount of args, will return the defval
fn (params &Params) get_arg_default(nr int, defval string) !string
fn (params &Params) get_default(key string, defval string) !string
fn (params &Params) get_default_false(key string) bool
fn (params &Params) get_default_true(key string) bool
fn (params &Params) get_float(key string) !f64
fn (params &Params) get_float_default(key string, defval f64) !f64
fn (params &Params) get_from_hashmap(key_ string, defval string, hashmap map[string]string) !string
fn (params &Params) get_int(key string) !int
fn (params &Params) get_int_default(key string, defval int) !int
//Looks for a list of strings in the parameters. ',' are used as deliminator to list
fn (params &Params) get_list(key string) ![]string
fn (params &Params) get_list_default(key string, def []string) ![]string
fn (params &Params) get_list_f32(key string) ![]f32
fn (params &Params) get_list_f32_default(key string, def []f32) []f32
fn (params &Params) get_list_f64(key string) ![]f64
fn (params &Params) get_list_f64_default(key string, def []f64) []f64
fn (params &Params) get_list_i16(key string) ![]i16
fn (params &Params) get_list_i16_default(key string, def []i16) []i16
fn (params &Params) get_list_i64(key string) ![]i64
fn (params &Params) get_list_i64_default(key string, def []i64) []i64
fn (params &Params) get_list_i8(key string) ![]i8
fn (params &Params) get_list_i8_default(key string, def []i8) []i8
fn (params &Params) get_list_int(key string) ![]int
fn (params &Params) get_list_int_default(key string, def []int) []int
fn (params &Params) get_list_namefix(key string) ![]string
fn (params &Params) get_list_namefix_default(key string, def []string) ![]string
fn (params &Params) get_list_u16(key string) ![]u16
fn (params &Params) get_list_u16_default(key string, def []u16) []u16
fn (params &Params) get_list_u32(key string) ![]u32
fn (params &Params) get_list_u32_default(key string, def []u32) []u32
fn (params &Params) get_list_u64(key string) ![]u64
fn (params &Params) get_list_u64_default(key string, def []u64) []u64
fn (params &Params) get_list_u8(key string) ![]u8
fn (params &Params) get_list_u8_default(key string, def []u8) []u8
fn (params &Params) get_map() map[string]string
fn (params &Params) get_path(key string) !string
fn (params &Params) get_path_create(key string) !string
fn (params &Params) get_percentage(key string) !f64
fn (params &Params) get_percentage_default(key string, defval string) !f64
//convert GB, MB, KB to bytes e.g. 10 GB becomes bytes in u64
fn (params &Params) get_storagecapacity_in_bytes(key string) !u64
fn (params &Params) get_storagecapacity_in_bytes_default(key string, defval u64) !u64
fn (params &Params) get_storagecapacity_in_gigabytes(key string) !u64
//Get Expiration object from time string input input can be either relative or absolute## Relative time
fn (params &Params) get_time(key string) !ourtime.OurTime
fn (params &Params) get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime
fn (params &Params) get_time_interval(key string) !Duration
fn (params &Params) get_timestamp(key string) !Duration
fn (params &Params) get_timestamp_default(key string, defval Duration) !Duration
fn (params &Params) get_u32(key string) !u32
fn (params &Params) get_u32_default(key string, defval u32) !u32
fn (params &Params) get_u64(key string) !u64
fn (params &Params) get_u64_default(key string, defval u64) !u64
fn (params &Params) get_u8(key string) !u8
fn (params &Params) get_u8_default(key string, defval u8) !u8
```
## how internally a heroscript gets parsed for params
- example to show how a heroscript gets parsed in action with params
- params are part of action object
```heroscript
example text to parse (heroscript)
id:a1 name6:aaaaa
name:'need to do something 1'
description:
'
## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
name2: test
name3: hi
name10:'this is with space' name11:aaa11
name4: 'aaa'
//somecomment
name5: 'aab'
```
the params are part of the action and are represented as follow for the above:
```vlang
Params{
params: [Param{
key: 'id'
value: 'a1'
}, Param{
key: 'name6'
value: 'aaaaa'
}, Param{
key: 'name'
value: 'need to do something 1'
}, Param{
key: 'description'
value: '## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
}, Param{
key: 'name2'
value: 'test'
}, Param{
key: 'name3'
value: 'hi'
}, Param{
key: 'name10'
value: 'this is with space'
}, Param{
key: 'name11'
value: 'aaa11'
}, Param{
key: 'name4'
value: 'aaa'
}, Param{
key: 'name5'
value: 'aab'
}]
}
```

View File

@@ -0,0 +1,73 @@
## `crypto.blake3` Module
```v
fn sum256(data []u8) []u8
```
Returns the Blake3 256-bit hash of the provided data.
```v
fn sum_derive_key256(context []u8, key_material []u8) []u8
```
Computes the Blake3 256-bit derived-key hash based on the context and key material.
```v
fn sum_keyed256(data []u8, key []u8) []u8
```
Returns the Blake3 256-bit keyed hash of the data using the specified key.
---
### Digest-Based API
```v
fn Digest.new_derive_key_hash(context []u8) !Digest
```
Initializes a `Digest` struct for creating a Blake3 derivedkey hash, using the provided context.
```v
fn Digest.new_hash() !Digest
```
Initializes a `Digest` struct for a standard (unkeyed) Blake3 hash.
```v
fn Digest.new_keyed_hash(key []u8) !Digest
```
Initializes a `Digest` struct for a keyed Blake3 hash, with the given key.
---
### `Digest` Methods
```v
fn (mut d Digest) write(data []u8) !
```
Feeds additional data bytes into the ongoing hash computation.
```v
fn (mut d Digest) checksum(size u64) []u8
```
Finalizes the hash and returns the resulting output.
* The `size` parameter specifies the number of output bytes—commonly `32` for a 256-bit digest, but can be up to `2**64`.
---
### Recommended Usage (in V)
```v
import crypto.blake3
mut hasher := crypto.blake3.Digest.new_hash() or { panic(err) }
hasher.write(data) or { panic(err) }
digest := hasher.checksum(24) // returns a []u8 of length 24 (192 bits)
```

View File

@@ -0,0 +1,45 @@
The `compress` module in V provides low-level functionalities for compressing and decompressing byte arrays.
**Functions Overview (Low-Level):**
* **`compress(data []u8, flags int) ![]u8`**: Compresses an array of bytes.
* **`decompress(data []u8, flags int) ![]u8`**: Decompresses an array of bytes.
* **`decompress_with_callback(data []u8, cb ChunkCallback, userdata voidptr, flags int) !u64`**: Decompresses byte arrays using a callback function for chunks.
**Type Definition (Low-Level):**
* **`ChunkCallback`**: A function type `fn (chunk []u8, userdata voidptr) int` used to receive decompressed chunks.
---
**`compress.gzip` Module (High-Level Gzip Operations):**
For high-level gzip compression and decompression, use the `compress.gzip` module. This module provides a more convenient and recommended way to handle gzip operations compared to the low-level `compress` module.
**Key Features of `compress.gzip`:**
* **`compress(data []u8, params CompressParams) ![]u8`**: Compresses data using gzip, allowing specification of `CompressParams` like `compression_level` (0-4095).
* **`decompress(data []u8, params DecompressParams) ![]u8`**: Decompresses gzip-compressed data, allowing specification of `DecompressParams` for verification.
* **`decompress_with_callback(data []u8, cb compr.ChunkCallback, userdata voidptr, params DecompressParams) !int`**: Decompresses gzip data with a callback for chunks, similar to the low-level version but for gzip streams.
* **`validate(data []u8, params DecompressParams) !GzipHeader`**: Validates a gzip header and returns its details.
**Parameter Structures:**
* **`CompressParams`**: Configures compression, primarily `compression_level` (0-4095).
* **`DecompressParams`**: Configures decompression, including `verify_header_checksum`, `verify_length`, and `verify_checksum`.
* **`GzipHeader`**: Represents the structure of a gzip header.
**Inline Code Example (Gzip Compression/Decompression):**
```v
import compress.gzip
data := 'Hello, Gzip!'
compressed := gzip.compress(data.bytes(), compression_level: 4095)!
decompressed := gzip.decompress(compressed)!
// Check if decompressed data matches original
// if data.bytes() == decompressed { ... }
```
**Important Note:** Always prefer `compress.gzip` for general gzip compression/decompression tasks over the low-level `compress` module.

View File

@@ -0,0 +1,64 @@
```v
struct Repo[T] {
db DB
}
struct User {
id int
name string
}
struct Post {
id int
user_id int
title string
body string
}
fn new_repo[T](db DB) Repo[T] {
return Repo[T]{db: db}
}
// This is a generic function. V will generate it for every type it's used with.
fn (r Repo[T]) find_by_id(id int) ?T {
table_name := T.name // in this example getting the name of the type gives us the table name
return r.db.query_one[T]('select * from ${table_name} where id = ?', id)
}
db := new_db()
users_repo := new_repo[User](db) // returns Repo[User]
posts_repo := new_repo[Post](db) // returns Repo[Post]
user := users_repo.find_by_id(1)? // find_by_id[User]
post := posts_repo.find_by_id(1)? // find_by_id[Post]
```
Currently generic function definitions must declare their type parameters, but in future V will infer generic type parameters from single-letter type names in runtime parameter types. This is why find_by_id can omit [T], because the receiver argument r uses a generic type T.
```v
fn compare[T](a T, b T) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
// compare[int]
println(compare(1, 0)) // Outputs: 1
println(compare(1, 1)) // 0
println(compare(1, 2)) // -1
// compare[string]
println(compare('1', '0')) // Outputs: 1
println(compare('1', '1')) // 0
println(compare('1', '2')) // -1
// compare[f64]
println(compare(1.1, 1.0)) // Outputs: 1
println(compare(1.1, 1.1)) // 0
println(compare(1.1, 1.2)) // -1
```

View File

@@ -6,21 +6,21 @@ module net
const msg_nosignal = 0x4000
const err_connection_refused = error_with_code('net: connection refused', errors_base + 10)
const err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
errors_base + 3)
errors_base + 3)
const opts_can_set = [
SocketOption.broadcast,
.debug,
.dont_route,
.keep_alive,
.linger,
.oob_inline,
.receive_buf_size,
.receive_low_size,
.receive_timeout,
.send_buf_size,
.send_low_size,
.send_timeout,
.ipv6_only,
SocketOption.broadcast,
.debug,
.dont_route,
.keep_alive,
.linger,
.oob_inline,
.receive_buf_size,
.receive_low_size,
.receive_timeout,
.send_buf_size,
.send_low_size,
.send_timeout,
.ipv6_only,
]
const error_eagain = C.EAGAIN
const err_port_out_of_range = error_with_code('net: port out of range', errors_base + 5)
@@ -29,12 +29,12 @@ const err_connect_failed = error_with_code('net: connect failed', errors_base +
const errors_base = 0
Well defined errors that are returned from socket functions
const opts_int = [
SocketOption.receive_buf_size,
.receive_low_size,
.receive_timeout,
.send_buf_size,
.send_low_size,
.send_timeout,
SocketOption.receive_buf_size,
.receive_low_size,
.receive_timeout,
.send_buf_size,
.send_low_size,
.send_timeout,
]
const error_eintr = C.EINTR
const error_ewouldblock = C.EWOULDBLOCK
@@ -43,17 +43,17 @@ const error_einprogress = C.EINPROGRESS
const err_timed_out_code = errors_base + 9
const err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8)
const err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
errors_base + 1)
errors_base + 1)
const msg_dontwait = C.MSG_DONTWAIT
const infinite_timeout = time.infinite
infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions only ever return with data)
const no_timeout = time.Duration(0)
no_timeout should be given to functions when no timeout is wanted (i.e. all functions return instantly)
const err_timed_out = error_with_code('net: op timed out', errors_base + 9)
const tcp_default_read_timeout = 30 * time.second
const tcp_default_read_timeout = 30 *time.second
const err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
errors_base + 2)
const tcp_default_write_timeout = 30 * time.second
errors_base + 2)
const tcp_default_write_timeout = 30* time.second
fn addr_from_socket_handle(handle int) Addr
addr_from_socket_handle returns an address, based on the given integer socket `handle`
fn close(handle int) !
@@ -94,16 +94,16 @@ fn validate_port(port int) !u16
validate_port checks whether a port is valid and returns the port or an error
fn wrap_error(error_code int) !
interface Connection {
addr() !Addr
peer_addr() !Addr
addr() !Addr
peer_addr() !Addr
mut:
read(mut []u8) !int
write([]u8) !int
close() !
read(mut []u8) !int
write([]u8) !int
close() !
}
Connection provides a generic SOCK_STREAM style interface that protocols can use as a base connection object to support TCP, UNIX Domain Sockets and various proxying solutions.
interface Dialer {
dial(address string) !Connection
dial(address string) !Connection
}
Dialer is an abstract dialer interface for producing connections to adresses.
fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) !
@@ -114,49 +114,49 @@ fn (mut s TcpSocket) bind(addr string) !
fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) !
fn (mut s UdpSocket) set_dualstack(on bool) !
enum AddrFamily {
unix = C.AF_UNIX
ip = C.AF_INET
ip6 = C.AF_INET6
unspec = C.AF_UNSPEC
unix = C.AF_UNIX
ip = C.AF_INET
ip6 = C.AF_INET6
unspec = C.AF_UNSPEC
}
AddrFamily are the available address families
enum ShutdownDirection {
read
write
read_and_write
read
write
read_and_write
}
ShutdownDirection is used by `net.shutdown`, for specifying the direction for which the communication will be cut.
enum SocketOption {
// TODO: SO_ACCEPT_CONN is not here because windows doesn't support it
// and there is no easy way to define it
broadcast = C.SO_BROADCAST
debug = C.SO_DEBUG
dont_route = C.SO_DONTROUTE
error = C.SO_ERROR
keep_alive = C.SO_KEEPALIVE
linger = C.SO_LINGER
oob_inline = C.SO_OOBINLINE
reuse_addr = C.SO_REUSEADDR
receive_buf_size = C.SO_RCVBUF
receive_low_size = C.SO_RCVLOWAT
receive_timeout = C.SO_RCVTIMEO
send_buf_size = C.SO_SNDBUF
send_low_size = C.SO_SNDLOWAT
send_timeout = C.SO_SNDTIMEO
socket_type = C.SO_TYPE
ipv6_only = C.IPV6_V6ONLY
// TODO: SO_ACCEPT_CONN is not here because windows doesn't support it
// and there is no easy way to define it
broadcast = C.SO_BROADCAST
debug = C.SO_DEBUG
dont_route = C.SO_DONTROUTE
error = C.SO_ERROR
keep_alive = C.SO_KEEPALIVE
linger = C.SO_LINGER
oob_inline = C.SO_OOBINLINE
reuse_addr = C.SO_REUSEADDR
receive_buf_size = C.SO_RCVBUF
receive_low_size = C.SO_RCVLOWAT
receive_timeout = C.SO_RCVTIMEO
send_buf_size = C.SO_SNDBUF
send_low_size = C.SO_SNDLOWAT
send_timeout = C.SO_SNDTIMEO
socket_type = C.SO_TYPE
ipv6_only = C.IPV6_V6ONLY
}
enum SocketType {
udp = C.SOCK_DGRAM
tcp = C.SOCK_STREAM
seqpacket = C.SOCK_SEQPACKET
udp = C.SOCK_DGRAM
tcp = C.SOCK_STREAM
seqpacket = C.SOCK_SEQPACKET
}
SocketType are the available sockets
struct Addr {
pub:
len u8
f u8
addr AddrData
len u8
f u8
addr AddrData
}
fn (a Addr) family() AddrFamily
family returns the family/kind of the given address `a`
@@ -168,72 +168,72 @@ fn (a Addr) str() string
str returns a string representation of the address `a`
struct C.addrinfo {
mut:
ai_family int
ai_socktype int
ai_flags int
ai_protocol int
ai_addrlen int
ai_addr voidptr
ai_canonname voidptr
ai_next voidptr
ai_family int
ai_socktype int
ai_flags int
ai_protocol int
ai_addrlen int
ai_addr voidptr
ai_canonname voidptr
ai_next voidptr
}
struct C.fd_set {}
struct C.sockaddr_in {
mut:
sin_len u8
sin_family u8
sin_port u16
sin_addr u32
sin_zero [8]char
sin_len u8
sin_family u8
sin_port u16
sin_addr u32
sin_zero [8]char
}
struct C.sockaddr_in6 {
mut:
// 1 + 1 + 2 + 4 + 16 + 4 = 28;
sin6_len u8 // 1
sin6_family u8 // 1
sin6_port u16 // 2
sin6_flowinfo u32 // 4
sin6_addr [16]u8 // 16
sin6_scope_id u32 // 4
// 1 + 1 + 2 + 4 + 16 + 4 = 28;
sin6_len u8 // 1
sin6_family u8 // 1
sin6_port u16 // 2
sin6_flowinfo u32 // 4
sin6_addr [16]u8 // 16
sin6_scope_id u32 // 4
}
struct C.sockaddr_un {
mut:
sun_len u8
sun_family u8
sun_path [max_unix_path]char
sun_len u8
sun_family u8
sun_path [max_unix_path]char
}
struct Ip {
port u16
addr [4]u8
// Pad to size so that socket functions
// dont complain to us (see in.h and bind())
// TODO(emily): I would really like to use
// some constant calculations here
// so that this doesnt have to be hardcoded
sin_pad [8]u8
port u16
addr [4]u8
// Pad to size so that socket functions
// dont complain to us (see in.h and bind())
// TODO(emily): I would really like to use
// some constant calculations here
// so that this doesnt have to be hardcoded
sin_pad [8]u8
}
fn (a Ip) str() string
str returns a string representation of `a`
struct Ip6 {
port u16
flow_info u32
addr [16]u8
scope_id u32
port u16
flow_info u32
addr [16]u8
scope_id u32
}
fn (a Ip6) str() string
str returns a string representation of `a`
struct ListenOptions {
pub:
dualstack bool = true
backlog int = 128
dualstack bool = true
backlog int = 128
}
struct ShutdownConfig {
pub:
how ShutdownDirection = .read_and_write
how ShutdownDirection = .read_and_write
}
struct Socket {
pub:
handle int
handle int
}
fn (s &Socket) address() !Addr
address gets the address of a socket
@@ -243,13 +243,13 @@ fn (t TCPDialer) dial(address string) !Connection
dial will try to create a new abstract connection to the given address. It will return an error, if that is not possible.
struct TcpConn {
pub mut:
sock TcpSocket
handle int
write_deadline time.Time
read_deadline time.Time
read_timeout time.Duration
write_timeout time.Duration
is_blocking bool = true
sock TcpSocket
handle int
write_deadline time.Time
read_deadline time.Time
read_timeout time.Duration
write_timeout time.Duration
is_blocking bool = true
}
fn (c &TcpConn) addr() !Addr
fn (mut c TcpConn) close() !
@@ -295,19 +295,17 @@ fn (mut c TcpConn) write_string(s string) !int
fn (c &TcpConn) write_timeout() time.Duration
struct TcpListener {
pub mut:
sock TcpSocket
accept_timeout time.Duration
accept_deadline time.Time
is_blocking bool = true
sock TcpSocket
accept_timeout time.Duration
accept_deadline time.Time
is_blocking bool = true
}
fn (mut l TcpListener) accept() !&TcpConn
accept a tcp connection from an external source to the listener `l`.
fn (mut l TcpListener) accept_only() !&TcpConn
accept_only accepts a tcp connection from an external source to the listener `l`. Unlike `accept`, `accept_only` *will not call* `.set_sock()!` on the result, and is thus faster.
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/vweb/vweb.v .
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/veb/veb.v .
If you do not need that, just call `.accept()!` instead, which will call `.set_sock()!` for you.
fn (c &TcpListener) accept_deadline() !time.Time
@@ -319,12 +317,12 @@ fn (mut c TcpListener) close() !
fn (c &TcpListener) addr() !Addr
struct UdpConn {
pub mut:
sock UdpSocket
sock UdpSocket
mut:
write_deadline time.Time
read_deadline time.Time
read_timeout time.Duration
write_timeout time.Duration
write_deadline time.Time
read_deadline time.Time
read_timeout time.Duration
write_timeout time.Duration
}
fn (mut c UdpConn) write_ptr(b &u8, len int) !int
sock := UdpSocket{ handle: sbase.handle l: local r: resolve_wrapper(raddr) } }
@@ -350,5 +348,5 @@ fn (mut c UdpConn) wait_for_write() !
fn (c &UdpConn) str() string
fn (mut c UdpConn) close() !
struct Unix {
path [max_unix_path]char
path [max_unix_path]char
}

View File

@@ -83,7 +83,7 @@ fn main() {
}
```
```vlang
```v
module time

View File

@@ -0,0 +1,785 @@
# module arrays
## Contents
- [append](#append)
- [binary_search](#binary_search)
- [carray_to_varray](#carray_to_varray)
- [chunk](#chunk)
- [chunk_while](#chunk_while)
- [concat](#concat)
- [copy](#copy)
- [distinct](#distinct)
- [each](#each)
- [each_indexed](#each_indexed)
- [filter_indexed](#filter_indexed)
- [find_first](#find_first)
- [find_last](#find_last)
- [flat_map](#flat_map)
- [flat_map_indexed](#flat_map_indexed)
- [flatten](#flatten)
- [fold](#fold)
- [fold_indexed](#fold_indexed)
- [group](#group)
- [group_by](#group_by)
- [idx_max](#idx_max)
- [idx_min](#idx_min)
- [index_of_first](#index_of_first)
- [index_of_last](#index_of_last)
- [join_to_string](#join_to_string)
- [lower_bound](#lower_bound)
- [map_indexed](#map_indexed)
- [map_of_counts](#map_of_counts)
- [map_of_indexes](#map_of_indexes)
- [max](#max)
- [merge](#merge)
- [min](#min)
- [partition](#partition)
- [reduce](#reduce)
- [reduce_indexed](#reduce_indexed)
- [reverse_iterator](#reverse_iterator)
- [rotate_left](#rotate_left)
- [rotate_right](#rotate_right)
- [sum](#sum)
- [uniq](#uniq)
- [uniq_all_repeated](#uniq_all_repeated)
- [uniq_only](#uniq_only)
- [uniq_only_repeated](#uniq_only_repeated)
- [upper_bound](#upper_bound)
- [window](#window)
- [ReverseIterator[T]](#ReverseIterator[T])
- [next](#next)
- [free](#free)
- [ReverseIterator](#ReverseIterator)
- [WindowAttribute](#WindowAttribute)
## append
```v
fn append[T](a []T, b []T) []T
```
append the second array `b` to the first array `a`, and return the result. Note, that unlike arrays.concat, arrays.append is less flexible, but more efficient, since it does not require you to use ...a for the second parameter.
Example
```v
arrays.append([1, 3, 5, 7], [2, 4, 6, 8]) // => [1, 3, 5, 7, 2, 4, 6, 8]
```
[[Return to contents]](#Contents)
## binary_search
```v
fn binary_search[T](array []T, target T) !int
```
binary_search, requires `array` to be sorted, returns index of found item or error. Binary searches on sorted lists can be faster than other array searches because at maximum the algorithm only has to traverse log N elements
Example
```v
arrays.binary_search([1, 2, 3, 4], 4)! // => 3
```
[[Return to contents]](#Contents)
## carray_to_varray
```v
fn carray_to_varray[T](c_array_data voidptr, items int) []T
```
carray_to_varray copies a C byte array into a V array of type `T`. See also: `cstring_to_vstring`
[[Return to contents]](#Contents)
## chunk
```v
fn chunk[T](array []T, size int) [][]T
```
chunk array into a single array of arrays where each element is the next `size` elements of the original.
Example
```v
arrays.chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) // => [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
```
[[Return to contents]](#Contents)
## chunk_while
```v
fn chunk_while[T](a []T, predicate fn (before T, after T) bool) [][]T
```
chunk_while splits the input array `a` into chunks of varying length, using the `predicate`, passing to it pairs of adjacent elements `before` and `after`. Each chunk, will contain all ajdacent elements, for which the `predicate` returned true. The chunks are split *between* the `before` and `after` elements, for which the `predicate` returned false.
Examples
```v
assert arrays.chunk_while([0,9,2,2,3,2,7,5,9,5],fn(x int,y int)bool{return x<=y})==[[0,9],[2,2,3],[2,7],[5,9],[5]]
assert arrays.chunk_while('aaaabbbcca'.runes(),fn(x rune,y rune)bool{return x==y})==[[`a`,`a`,`a`,`a`],[`b`,`b`,`b`],[`c`,`c`],[`a`]]
assert arrays.chunk_while('aaaabbbcca'.runes(),fn(x rune,y rune)bool{return x==y}).map({it[0]:it.len})==[{`a`:4},{`b`:3},{`c`:2},{`a`:1}]
```
[[Return to contents]](#Contents)
## concat
```v
fn concat[T](a []T, b ...T) []T
```
concatenate an array with an arbitrary number of additional values.
Note: if you have two arrays, you should simply use the `<<` operator directly.
Examples
```v
assert arrays.concat([1, 2, 3], 4, 5, 6) == [1, 2, 3, 4, 5, 6]
assert arrays.concat([1, 2, 3], ...[4, 5, 6]) == [1, 2, 3, 4, 5, 6]
mut arr := arrays.concat([1, 2, 3], 4); arr << [10,20]; assert arr == [1,2,3,4,10,20] // note: arr is mutable
```
[[Return to contents]](#Contents)
## copy
```v
fn copy[T](mut dst []T, src []T) int
```
copy copies the `src` array elements to the `dst` array. The number of the elements copied is the minimum of the length of both arrays. Returns the number of elements copied.
[[Return to contents]](#Contents)
## distinct
```v
fn distinct[T](a []T) []T
```
distinct returns all distinct elements from the given array a. The results are guaranteed to be unique, i.e. not have duplicates. See also arrays.uniq, which can be used to achieve the same goal, but needs you to first sort the array.
Example
```v
assert arrays.distinct( [5, 5, 1, 5, 2, 1, 1, 9] ) == [1, 2, 5, 9]
```
[[Return to contents]](#Contents)
## each
```v
fn each[T](a []T, cb fn (elem T))
```
each calls the callback fn `cb`, for each element of the given array `a`.
[[Return to contents]](#Contents)
## each_indexed
```v
fn each_indexed[T](a []T, cb fn (i int, e T))
```
each_indexed calls the callback fn `cb`, for each element of the given array `a`. It passes the callback both the index of the current element, and the element itself.
[[Return to contents]](#Contents)
## filter_indexed
```v
fn filter_indexed[T](array []T, predicate fn (idx int, elem T) bool) []T
```
filter_indexed filters elements based on `predicate` function being invoked on each element with its index in the original array.
[[Return to contents]](#Contents)
## find_first
```v
fn find_first[T](array []T, predicate fn (elem T) bool) ?T
```
find_first returns the first element that matches the given predicate. Returns `none` if no match is found.
Example
```v
arrays.find_first([1, 2, 3, 4, 5], fn (i int) bool { return i == 3 })? // => 3
```
[[Return to contents]](#Contents)
## find_last
```v
fn find_last[T](array []T, predicate fn (elem T) bool) ?T
```
find_last returns the last element that matches the given predicate. Returns `none` if no match is found.
Example
```v
arrays.find_last([1, 2, 3, 4, 5], fn (i int) bool { return i == 3})? // => 3
```
[[Return to contents]](#Contents)
## flat_map
```v
fn flat_map[T, R](array []T, transform fn (elem T) []R) []R
```
flat_map creates a new array populated with the flattened result of calling transform function being invoked on each element of `list`.
[[Return to contents]](#Contents)
## flat_map_indexed
```v
fn flat_map_indexed[T, R](array []T, transform fn (idx int, elem T) []R) []R
```
flat_map_indexed creates a new array with the flattened result of calling the `transform` fn, invoked on each idx,elem pair from the original.
[[Return to contents]](#Contents)
## flatten
```v
fn flatten[T](array [][]T) []T
```
flatten flattens n + 1 dimensional array into n dimensional array.
Example
```v
arrays.flatten[int]([[1, 2, 3], [4, 5]]) // => [1, 2, 3, 4, 5]
```
[[Return to contents]](#Contents)
## fold
```v
fn fold[T, R](array []T, init R, fold_op fn (acc R, elem T) R) R
```
fold sets `acc = init`, then successively calls `acc = fold_op(acc, elem)` for each element in `array`. returns `acc`.
Example
```v
// Sum the length of each string in an array
a := ['Hi', 'all']
r := arrays.fold[string, int](a, 0,
fn (r int, t string) int { return r + t.len })
assert r == 5
```
[[Return to contents]](#Contents)
## fold_indexed
```v
fn fold_indexed[T, R](array []T, init R, fold_op fn (idx int, acc R, elem T) R) R
```
fold_indexed sets `acc = init`, then successively calls `acc = fold_op(idx, acc, elem)` for each element in `array`. returns `acc`.
[[Return to contents]](#Contents)
## group
```v
fn group[T](arrs ...[]T) [][]T
```
group n arrays into a single array of arrays with n elements. This function is analogous to the "zip" function of other languages. To fully interleave two arrays, follow this function with a call to `flatten`.
Note: An error will be generated if the type annotation is omitted.
Example
```v
arrays.group[int]([1, 2, 3], [4, 5, 6]) // => [[1, 4], [2, 5], [3, 6]]
```
[[Return to contents]](#Contents)
## group_by
```v
fn group_by[K, V](array []V, grouping_op fn (val V) K) map[K][]V
```
group_by groups together elements, for which the `grouping_op` callback produced the same result.
Example
```v
arrays.group_by[int, string](['H', 'el', 'lo'], fn (v string) int { return v.len }) // => {1: ['H'], 2: ['el', 'lo']}
```
[[Return to contents]](#Contents)
## idx_max
```v
fn idx_max[T](array []T) !int
```
idx_max returns the index of the maximum value in the array.
Example
```v
arrays.idx_max([1, 2, 3, 0, 9])! // => 4
```
[[Return to contents]](#Contents)
## idx_min
```v
fn idx_min[T](array []T) !int
```
idx_min returns the index of the minimum value in the array.
Example
```v
arrays.idx_min([1, 2, 3, 0, 9])! // => 3
```
[[Return to contents]](#Contents)
## index_of_first
```v
fn index_of_first[T](array []T, predicate fn (idx int, elem T) bool) int
```
index_of_first returns the index of the first element of `array`, for which the predicate fn returns true. If predicate does not return true for any of the elements, then index_of_first will return -1.
Example
```v
assert arrays.index_of_first([4,5,0,7,0,9], fn(idx int, x int) bool { return x == 0 }) == 2
```
[[Return to contents]](#Contents)
## index_of_last
```v
fn index_of_last[T](array []T, predicate fn (idx int, elem T) bool) int
```
index_of_last returns the index of the last element of `array`, for which the predicate fn returns true. If predicate does not return true for any of the elements, then index_of_last will return -1.
Example
```v
assert arrays.index_of_last([4,5,0,7,0,9], fn(idx int, x int) bool { return x == 0 }) == 4
```
[[Return to contents]](#Contents)
## join_to_string
```v
fn join_to_string[T](array []T, separator string, transform fn (elem T) string) string
```
join_to_string takes in a custom transform function and joins all elements into a string with the specified separator
[[Return to contents]](#Contents)
## lower_bound
```v
fn lower_bound[T](array []T, val T) !T
```
returns the smallest element >= val, requires `array` to be sorted.
Example
```v
arrays.lower_bound([2, 4, 6, 8], 3)! // => 4
```
[[Return to contents]](#Contents)
## map_indexed
```v
fn map_indexed[T, R](array []T, transform fn (idx int, elem T) R) []R
```
map_indexed creates a new array with the result of calling the `transform` fn, invoked on each idx,elem pair from the original.
[[Return to contents]](#Contents)
## map_of_counts
```v
fn map_of_counts[T](array []T) map[T]int
```
map_of_counts returns a map, where each key is an unique value in `array`. Each value in that map for that key, is how many times that value occurs in `array`. It can be useful for building histograms of discrete measurements.
Example
```v
assert arrays.map_of_counts([1,2,3,4,4,2,1,4,4]) == {1: 2, 2: 2, 3: 1, 4: 4}
```
[[Return to contents]](#Contents)
## map_of_indexes
```v
fn map_of_indexes[T](array []T) map[T][]int
```
map_of_indexes returns a map, where each key is an unique value in `array`. Each value in that map for that key, is an array, containing the indexes in `array`, where that value has been found.
Example
```v
assert arrays.map_of_indexes([1,2,3,4,4,2,1,4,4,999]) == {1: [0, 6], 2: [1, 5], 3: [2], 4: [3, 4, 7, 8], 999: [9]}
```
[[Return to contents]](#Contents)
## max
```v
fn max[T](array []T) !T
```
max returns the maximum value in the array.
Example
```v
arrays.max([1, 2, 3, 0, 9])! // => 9
```
[[Return to contents]](#Contents)
## merge
```v
fn merge[T](a []T, b []T) []T
```
merge two sorted arrays (ascending) and maintain sorted order.
Example
```v
arrays.merge([1, 3, 5, 7], [2, 4, 6, 8]) // => [1, 2, 3, 4, 5, 6, 7, 8]
```
[[Return to contents]](#Contents)
## min
```v
fn min[T](array []T) !T
```
min returns the minimum value in the array.
Example
```v
arrays.min([1, 2, 3, 0, 9])! // => 0
```
[[Return to contents]](#Contents)
## partition
```v
fn partition[T](array []T, predicate fn (elem T) bool) ([]T, []T)
```
partition splits the original array into pair of lists. The first list contains elements for which the predicate fn returned true, while the second list contains elements for which the predicate fn returned false.
[[Return to contents]](#Contents)
## reduce
```v
fn reduce[T](array []T, reduce_op fn (acc T, elem T) T) !T
```
reduce sets `acc = array[0]`, then successively calls `acc = reduce_op(acc, elem)` for each remaining element in `array`. returns the accumulated value in `acc`. returns an error if the array is empty. See also: [fold](#fold).
Example
```v
arrays.reduce([1, 2, 3, 4, 5], fn (t1 int, t2 int) int { return t1 * t2 })! // => 120
```
[[Return to contents]](#Contents)
## reduce_indexed
```v
fn reduce_indexed[T](array []T, reduce_op fn (idx int, acc T, elem T) T) !T
```
reduce_indexed sets `acc = array[0]`, then successively calls `acc = reduce_op(idx, acc, elem)` for each remaining element in `array`. returns the accumulated value in `acc`. returns an error if the array is empty. See also: [fold_indexed](#fold_indexed).
[[Return to contents]](#Contents)
## reverse_iterator
```v
fn reverse_iterator[T](a []T) ReverseIterator[T]
```
reverse_iterator can be used to iterate over the elements in an array. i.e. you can use this syntax: `for elem in arrays.reverse_iterator(a) {` .
[[Return to contents]](#Contents)
## rotate_left
```v
fn rotate_left[T](mut array []T, mid int)
```
rotate_left rotates the array in-place. It does it in such a way, that the first `mid` elements of the array, move to the end, while the last `array.len - mid` elements move to the front. After calling `rotate_left`, the element previously at index `mid` will become the first element in the array.
Example
```v
mut x := [1,2,3,4,5,6]
arrays.rotate_left(mut x, 2)
println(x) // [3, 4, 5, 6, 1, 2]
```
[[Return to contents]](#Contents)
## rotate_right
```v
fn rotate_right[T](mut array []T, k int)
```
rotate_right rotates the array in-place. It does it in such a way, that the first `array.len - k` elements of the array, move to the end, while the last `k` elements move to the front. After calling `rotate_right`, the element previously at index `array.len - k` will become the first element in the array.
Example
```v
mut x := [1,2,3,4,5,6]
arrays.rotate_right(mut x, 2)
println(x) // [5, 6, 1, 2, 3, 4]
```
[[Return to contents]](#Contents)
## sum
```v
fn sum[T](array []T) !T
```
sum up array, return an error, when the array has no elements.
Example
```v
arrays.sum([1, 2, 3, 4, 5])! // => 15
```
[[Return to contents]](#Contents)
## uniq
```v
fn uniq[T](a []T) []T
```
uniq filters the adjacent matching elements from the given array. All adjacent matching elements, are merged to their first occurrence, so the output will have no repeating elements.
Note: `uniq` does not detect repeats, unless they are adjacent. You may want to call a.sorted() on your array, before passing the result to arrays.uniq(). See also arrays.distinct, which is essentially arrays.uniq(a.sorted()) .
Examples
```v
assert arrays.uniq( []int{} ) == []
assert arrays.uniq( [1, 1] ) == [1]
assert arrays.uniq( [2, 1] ) == [2, 1]
assert arrays.uniq( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 1, 5, 2, 1, 9]
```
[[Return to contents]](#Contents)
## uniq_all_repeated
```v
fn uniq_all_repeated[T](a []T) []T
```
uniq_all_repeated produces all adjacent matching elements from the given array. Unique elements, with no duplicates are removed. The output will contain all the duplicated elements, repeated just like they were in the original.
Note: `uniq_all_repeated` does not detect repeats, unless they are adjacent. You may want to call a.sorted() on your array, before passing the result to arrays.uniq_all_repeated().
Examples
```v
assert arrays.uniq_all_repeated( []int{} ) == []
assert arrays.uniq_all_repeated( [1, 5] ) == []
assert arrays.uniq_all_repeated( [5, 5] ) == [5,5]
assert arrays.uniq_all_repeated( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 5, 1, 1]
```
[[Return to contents]](#Contents)
## uniq_only
```v
fn uniq_only[T](a []T) []T
```
uniq_only filters the adjacent matching elements from the given array. All adjacent matching elements, are removed. The output will contain only the elements that *did not have* any adjacent matches.
Note: `uniq_only` does not detect repeats, unless they are adjacent. You may want to call a.sorted() on your array, before passing the result to arrays.uniq_only().
Examples
```v
assert arrays.uniq_only( []int{} ) == []
assert arrays.uniq_only( [1, 1] ) == []
assert arrays.uniq_only( [2, 1] ) == [2, 1]
assert arrays.uniq_only( [1, 5, 5, 1, 5, 2, 1, 1, 9] ) == [1, 1, 5, 2, 9]
```
[[Return to contents]](#Contents)
## uniq_only_repeated
```v
fn uniq_only_repeated[T](a []T) []T
```
uniq_only_repeated produces the adjacent matching elements from the given array. Unique elements, with no duplicates are removed. Adjacent matching elements, are reduced to just 1 element per repeat group.
Note: `uniq_only_repeated` does not detect repeats, unless they are adjacent. You may want to call a.sorted() on your array, before passing the result to arrays.uniq_only_repeated().
Examples
```v
assert arrays.uniq_only_repeated( []int{} ) == []
assert arrays.uniq_only_repeated( [1, 5] ) == []
assert arrays.uniq_only_repeated( [5, 5] ) == [5]
assert arrays.uniq_only_repeated( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 1]
```
[[Return to contents]](#Contents)
## upper_bound
```v
fn upper_bound[T](array []T, val T) !T
```
returns the largest element <= val, requires `array` to be sorted.
Example
```v
arrays.upper_bound([2, 4, 6, 8], 3)! // => 2
```
[[Return to contents]](#Contents)
## window
```v
fn window[T](array []T, attr WindowAttribute) [][]T
```
get snapshots of the window of the given size sliding along array with the given step, where each snapshot is an array.- `size` - snapshot size
- `step` - gap size between each snapshot, default is 1.
Examples
```v
arrays.window([1, 2, 3, 4], size: 2) // => [[1, 2], [2, 3], [3, 4]]
arrays.window([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], size: 3, step: 2) // => [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]]
```
[[Return to contents]](#Contents)
## ReverseIterator[T]
## next
```v
fn (mut iter ReverseIterator[T]) next() ?&T
```
next is the required method, to implement an iterator in V. It returns none when the iteration should stop. Otherwise it returns the current element of the array.
[[Return to contents]](#Contents)
## free
```v
fn (iter &ReverseIterator[T]) free()
```
free frees the iterator resources.
[[Return to contents]](#Contents)
## ReverseIterator
```v
struct ReverseIterator[T] {
mut:
a []T
i int
}
```
ReverseIterator provides a convenient way to iterate in reverse over all elements of an array without allocations. I.e. it allows you to use this syntax: `for elem in arrays.reverse_iterator(a) {` .
[[Return to contents]](#Contents)
## WindowAttribute
```v
struct WindowAttribute {
pub:
size int
step int = 1
}
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:19:06

View File

@@ -0,0 +1,76 @@
# module diff
## Contents
- [diff](#diff)
- [DiffContext[T]](#DiffContext[T])
- [generate_patch](#generate_patch)
- [DiffChange](#DiffChange)
- [DiffContext](#DiffContext)
- [DiffGenStrParam](#DiffGenStrParam)
## diff
```v
fn diff[T](a []T, b []T) &DiffContext[T]
```
diff returns the difference of two arrays.
[[Return to contents]](#Contents)
## DiffContext[T]
## generate_patch
```v
fn (mut c DiffContext[T]) generate_patch(param DiffGenStrParam) string
```
generate_patch generate a diff string of two arrays.
[[Return to contents]](#Contents)
## DiffChange
```v
struct DiffChange {
pub mut:
a int // position in input a []T
b int // position in input b []T
del int // delete Del elements from input a
ins int // insert Ins elements from input b
}
```
DiffChange contains one or more deletions or inserts at one position in two arrays.
[[Return to contents]](#Contents)
## DiffContext
```v
struct DiffContext[T] {
mut:
a []T
b []T
flags []DiffContextFlag
max int
// forward and reverse d-path endpoint x components
forward []int
reverse []int
pub mut:
changes []DiffChange
}
```
[[Return to contents]](#Contents)
## DiffGenStrParam
```v
struct DiffGenStrParam {
pub mut:
colorful bool
unified int = 3 // how many context lines before/after diff block
block_header bool // output `@@ -3,4 +3,5 @@` or not
}
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:19:06

View File

@@ -0,0 +1,53 @@
# module parallel
## Contents
- [amap](#amap)
- [run](#run)
- [Params](#Params)
## amap
```v
fn amap[T, R](input []T, worker fn (T) R, opt Params) []R
```
amap lets the user run an array of input with a user provided function in parallel. It limits the number of worker threads to max number of cpus. The worker function can return a value. The returning array maintains the input order. Any error handling should have happened within the worker function.
Example
```v
squares := parallel.amap([1, 2, 3, 4, 5], |i| i * i); assert squares == [1, 4, 9, 16, 25]
```
[[Return to contents]](#Contents)
## run
```v
fn run[T](input []T, worker fn (T), opt Params)
```
run lets the user run an array of input with a user provided function in parallel. It limits the number of worker threads to min(num_workers, num_cpu). The function aborts if an error is encountered.
Example
```v
parallel.run([1, 2, 3, 4, 5], |i| println(i))
```
[[Return to contents]](#Contents)
## Params
```v
struct Params {
pub mut:
workers int // 0 by default, so that VJOBS will be used, through runtime.nr_jobs()
}
```
Params contains the optional parameters that can be passed to `run` and `amap`.
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:19:06

View File

@@ -0,0 +1,321 @@
# module benchmark
## Contents
- [Constants](#Constants)
- [new_benchmark](#new_benchmark)
- [new_benchmark_no_cstep](#new_benchmark_no_cstep)
- [new_benchmark_pointer](#new_benchmark_pointer)
- [start](#start)
- [Benchmark](#Benchmark)
- [set_total_expected_steps](#set_total_expected_steps)
- [stop](#stop)
- [step](#step)
- [step_restart](#step_restart)
- [fail](#fail)
- [ok](#ok)
- [skip](#skip)
- [fail_many](#fail_many)
- [ok_many](#ok_many)
- [neither_fail_nor_ok](#neither_fail_nor_ok)
- [measure](#measure)
- [record_measure](#record_measure)
- [step_message_with_label_and_duration](#step_message_with_label_and_duration)
- [step_message_with_label](#step_message_with_label)
- [step_message](#step_message)
- [step_message_ok](#step_message_ok)
- [step_message_fail](#step_message_fail)
- [step_message_skip](#step_message_skip)
- [total_message](#total_message)
- [all_recorded_measures](#all_recorded_measures)
- [total_duration](#total_duration)
- [MessageOptions](#MessageOptions)
## Constants
```v
const b_ok = term.ok_message('OK ')
```
[[Return to contents]](#Contents)
```v
const b_fail = term.fail_message('FAIL')
```
[[Return to contents]](#Contents)
```v
const b_skip = term.warn_message('SKIP')
```
[[Return to contents]](#Contents)
```v
const b_spent = term.ok_message('SPENT')
```
[[Return to contents]](#Contents)
## new_benchmark
```v
fn new_benchmark() Benchmark
```
new_benchmark returns a `Benchmark` instance on the stack.
[[Return to contents]](#Contents)
## new_benchmark_no_cstep
```v
fn new_benchmark_no_cstep() Benchmark
```
new_benchmark_no_cstep returns a new `Benchmark` instance with step counting disabled.
[[Return to contents]](#Contents)
## new_benchmark_pointer
```v
fn new_benchmark_pointer() &Benchmark
```
new_benchmark_pointer returns a new `Benchmark` instance allocated on the heap. This is useful for long-lived use of `Benchmark` instances.
[[Return to contents]](#Contents)
## start
```v
fn start() Benchmark
```
start returns a new, running, instance of `Benchmark`. This is a shorthand for calling `new_benchmark().step()`.
[[Return to contents]](#Contents)
## Benchmark
```v
struct Benchmark {
pub mut:
bench_timer time.StopWatch
verbose bool
no_cstep bool
step_timer time.StopWatch
ntotal int
nok int
nfail int
nskip int
nexpected_steps int
njobs int
cstep int
bok string
bfail string
measured_steps []string
step_data map[string][]f64
}
```
[[Return to contents]](#Contents)
## set_total_expected_steps
```v
fn (mut b Benchmark) set_total_expected_steps(n int)
```
set_total_expected_steps sets the total amount of steps the benchmark is expected to take.
[[Return to contents]](#Contents)
## stop
```v
fn (mut b Benchmark) stop()
```
stop stops the internal benchmark timer.
[[Return to contents]](#Contents)
## step
```v
fn (mut b Benchmark) step()
```
step increases the step count by 1 and restarts the internal timer.
[[Return to contents]](#Contents)
## step_restart
```v
fn (mut b Benchmark) step_restart()
```
step_restart will restart the internal step timer. Note that the step count will *stay the same*. This method is useful, when you want to do some optional preparation after you have called .step(), so that the time for that optional preparation will *not* be added to the duration of the step.
[[Return to contents]](#Contents)
## fail
```v
fn (mut b Benchmark) fail()
```
fail increases the fail count by 1 and stops the internal timer.
[[Return to contents]](#Contents)
## ok
```v
fn (mut b Benchmark) ok()
```
ok increases the ok count by 1 and stops the internal timer.
[[Return to contents]](#Contents)
## skip
```v
fn (mut b Benchmark) skip()
```
skip increases the skip count by 1 and stops the internal timer.
[[Return to contents]](#Contents)
## fail_many
```v
fn (mut b Benchmark) fail_many(n int)
```
fail_many increases the fail count by `n` and stops the internal timer.
[[Return to contents]](#Contents)
## ok_many
```v
fn (mut b Benchmark) ok_many(n int)
```
ok_many increases the ok count by `n` and stops the internal timer.
[[Return to contents]](#Contents)
## neither_fail_nor_ok
```v
fn (mut b Benchmark) neither_fail_nor_ok()
```
neither_fail_nor_ok stops the internal timer.
[[Return to contents]](#Contents)
## measure
```v
fn (mut b Benchmark) measure(label string) i64
```
measure prints the current time spent doing `label`, since the benchmark was started, or since its last call.
[[Return to contents]](#Contents)
## record_measure
```v
fn (mut b Benchmark) record_measure(label string) i64
```
record_measure stores the current time doing `label`, since the benchmark was started, or since the last call to `b.record_measure`. It is similar to `b.measure`, but unlike it, will not print the measurement immediately, just record it for later. You can call `b.all_recorded_measures` to retrieve all measures stored by `b.record_measure` calls.
[[Return to contents]](#Contents)
## step_message_with_label_and_duration
```v
fn (b &Benchmark) step_message_with_label_and_duration(label string, msg string, sduration time.Duration,
opts MessageOptions) string
```
step_message_with_label_and_duration returns a string describing the current step.
[[Return to contents]](#Contents)
## step_message_with_label
```v
fn (b &Benchmark) step_message_with_label(label string, msg string, opts MessageOptions) string
```
step_message_with_label returns a string describing the current step using current time as duration.
[[Return to contents]](#Contents)
## step_message
```v
fn (b &Benchmark) step_message(msg string, opts MessageOptions) string
```
step_message returns a string describing the current step.
[[Return to contents]](#Contents)
## step_message_ok
```v
fn (b &Benchmark) step_message_ok(msg string, opts MessageOptions) string
```
step_message_ok returns a string describing the current step with an standard "OK" label.
[[Return to contents]](#Contents)
## step_message_fail
```v
fn (b &Benchmark) step_message_fail(msg string, opts MessageOptions) string
```
step_message_fail returns a string describing the current step with an standard "FAIL" label.
[[Return to contents]](#Contents)
## step_message_skip
```v
fn (b &Benchmark) step_message_skip(msg string, opts MessageOptions) string
```
step_message_skip returns a string describing the current step with an standard "SKIP" label.
[[Return to contents]](#Contents)
## total_message
```v
fn (b &Benchmark) total_message(msg string) string
```
total_message returns a string with total summary of the benchmark run.
[[Return to contents]](#Contents)
## all_recorded_measures
```v
fn (b &Benchmark) all_recorded_measures() string
```
all_recorded_measures returns a string, that contains all the recorded measure messages, done by individual calls to `b.record_measure`.
[[Return to contents]](#Contents)
## total_duration
```v
fn (b &Benchmark) total_duration() i64
```
total_duration returns the duration in ms.
[[Return to contents]](#Contents)
## MessageOptions
```v
struct MessageOptions {
pub:
preparation time.Duration // the duration of the preparation time for the step
}
```
MessageOptions allows passing an optional preparation time too to each label method. If it is set, the preparation time (compile time) will be shown before the measured runtime.
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:21:08

View File

@@ -0,0 +1,22 @@
# module builtin.linux_bare.old..checks.forkedtest
## Contents
- [normal_run](#normal_run)
- [run](#run)
## normal_run
```v
fn normal_run(op fn (), label string) int
```
[[Return to contents]](#Contents)
## run
```v
fn run(op fn (), label string, code Wi_si_code, status int) int
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:18:39

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,220 @@
# module closure
## Contents
- [Constants](#Constants)
- [C.pthread_mutex_t](#C.pthread_mutex_t)
## Constants
```v
const closure_thunk = $if amd64 {
[
u8(0xF3),
0x44,
0x0F,
0x7E,
0x3D,
0xF7,
0xBF,
0xFF,
0xFF, // movq xmm15, QWORD PTR [rip - userdata]
0xFF,
0x25,
0xF9,
0xBF,
0xFF,
0xFF, // jmp QWORD PTR [rip - fn]
]
} $else $if i386 {
[
u8(0xe8),
0x00,
0x00,
0x00,
0x00, // call here
// here:
0x59, // pop ecx
0x66,
0x0F,
0x6E,
0xF9, // movd xmm7, ecx
0xff,
0xA1,
0xff,
0xbf,
0xff,
0xff, // jmp DWORD PTR [ecx - 0x4001] # <fn>
]
} $else $if arm64 {
[
u8(0x11),
0x00,
0xFE,
0x5C, // ldr d17, userdata
0x30,
0x00,
0xFE,
0x58, // ldr x16, fn
0x00,
0x02,
0x1F,
0xD6, // br x16
]
} $else $if arm32 {
[
u8(0x04),
0xC0,
0x4F,
0xE2, // adr ip, here
// here:
0x01,
0xC9,
0x4C,
0xE2, // sub ip, ip, #0x4000
0x90,
0xCA,
0x07,
0xEE, // vmov s15, ip
0x00,
0xC0,
0x9C,
0xE5, // ldr ip, [ip, 0]
0x1C,
0xFF,
0x2F,
0xE1, // bx ip
]
} $else $if rv64 {
[
u8(0x97),
0xCF,
0xFF,
0xFF, // auipc t6, 0xffffc
0x03,
0xBF,
0x8F,
0x00, // ld t5, 8(t6)
0x07,
0xB3,
0x0F,
0x00, // fld ft6, 0(t6)
0x67,
0x00,
0x0F,
0x00, // jr t5
]
} $else $if rv32 {
[
u8(0x97),
0xCF,
0xFF,
0xFF, // auipc t6, 0xffffc
0x03,
0xAF,
0x4F,
0x00, // lw t5, 4(t6)
0x07,
0xAB,
0x0F,
0x00, // flw fs6, 0(t6)
0x67,
0x00,
0x0F,
0x00, // jr t5
]
} $else $if s390x {
[
u8(0xC0),
0x70,
0xFF,
0xFF,
0xE0,
0x00, // larl %r7, -16384
0x68,
0xF0,
0x70,
0x00, // ld %f15, 0(%r7)
0xE3,
0x70,
0x70,
0x08,
0x00,
0x04, // lg %r7, 8(%r7)
0x07,
0xF7, // br %r7
]
} $else $if ppc64le {
[
u8(0xa6),
0x02,
0x08,
0x7c, // mflr %r0
0x05,
0x00,
0x00,
0x48, // bl here
0xa6,
0x02,
0xc8,
0x7d, // here: mflr %r14
0xf8,
0xbf,
0xce,
0x39, // addi %r14, %r14, -16392
0x00,
0x00,
0xce,
0xc9, // lfd %f14, 0(%r14)
0x08,
0x00,
0xce,
0xe9, // ld %r14, 8(%r14)
0xa6,
0x03,
0x08,
0x7c, // mtlr %r0
0xa6,
0x03,
0xc9,
0x7d, // mtctr %r14
0x20,
0x04,
0x80,
0x4e, // bctr
]
} $else $if loongarch64 {
[
u8(0x92),
0xFF,
0xFF,
0x1D, // pcaddu12i t6, -4
0x48,
0x02,
0x80,
0x2B, // fld.d f8, t6, 0
0x51,
0x22,
0xC0,
0x28, // ld.d t5, t6, 8
0x20,
0x02,
0x00,
0x4C, // jr t5
]
} $else {
[]u8{}
}
```
refer to https://godbolt.org/z/r7P3EYv6c for a complete assembly vfmt off
[[Return to contents]](#Contents)
## C.pthread_mutex_t
```v
struct C.pthread_mutex_t {}
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:18:39

View File

@@ -0,0 +1,135 @@
# module wchar
## Contents
- [Constants](#Constants)
- [from_rune](#from_rune)
- [from_string](#from_string)
- [length_in_bytes](#length_in_bytes)
- [length_in_characters](#length_in_characters)
- [to_string](#to_string)
- [to_string2](#to_string2)
- [Character](#Character)
- [str](#str)
- [==](#==)
- [to_rune](#to_rune)
- [C.wchar_t](#C.wchar_t)
## Constants
```v
const zero = from_rune(0)
```
zero is a Character, that in C L"" strings represents the string end character (terminator).
[[Return to contents]](#Contents)
## from_rune
```v
fn from_rune(r rune) Character
```
from_rune creates a Character, given a V rune
[[Return to contents]](#Contents)
## from_string
```v
fn from_string(s string) &Character
```
from_string converts the V string (in UTF-8 encoding), into a newly allocated platform specific buffer of C.wchar_t . The conversion is done by processing each rune of the input string 1 by 1.
[[Return to contents]](#Contents)
## length_in_bytes
```v
fn length_in_bytes(p voidptr) int
```
length_in_bytes returns the length of the given wchar_t* wide C style L"" string in bytes. Note that the size of wchar_t is different on the different platforms, thus the length in bytes for the same data converted from UTF-8 to a &Character buffer, will be different as well. i.e. unsafe { wchar.length_in_bytes(wchar.from_string('abc')) } will be 12 on unix, but 6 on windows.
[[Return to contents]](#Contents)
## length_in_characters
```v
fn length_in_characters(p voidptr) int
```
See also `length_in_bytes` .
Example
```v
assert unsafe { wchar.length_in_characters(wchar.from_string('abc')) } == 3
```
[[Return to contents]](#Contents)
## to_string
```v
fn to_string(p voidptr) string
```
to_string creates a V string, encoded in UTF-8, given a wchar_t* wide C style L"" string. It relies that the string has a 0 terminator at its end, to determine the string's length. Note, that the size of wchar_t is platform-dependent, and is *2 bytes* on windows, while it is *4 bytes* on most everything else. Unless you are interfacing with a C library, that does specifically use `wchar_t`, consider using `string_from_wide` instead, which will always assume that the input data is in an UTF-16 encoding, no matter what the platform is.
[[Return to contents]](#Contents)
## to_string2
```v
fn to_string2(p voidptr, len int) string
```
to_string2 creates a V string, encoded in UTF-8, given a `C.wchar_t*` wide C style L"" string. Note, that the size of `C.wchar_t` is platform-dependent, and is *2 bytes* on windows, while *4* on most everything else. Unless you are interfacing with a C library, that does specifically use wchar_t, consider using string_from_wide2 instead, which will always assume that the input data is in an UTF-16 encoding, no matter what the platform is.
[[Return to contents]](#Contents)
## Character
```v
type Character = C.wchar_t
```
Character is a type, that eases working with the platform dependent C.wchar_t type.
Note: the size of C.wchar_t varies between platforms, it is 2 bytes on windows, and usually 4 bytes elsewhere.
[[Return to contents]](#Contents)
## str
```v
fn (a Character) str() string
```
return a string representation of the given Character
[[Return to contents]](#Contents)
## ==
```v
fn (a Character) == (b Character) bool
```
== is an equality operator, to ease comparing Characters
Todo: the default == operator, that V generates, does not work for C.wchar_t .
[[Return to contents]](#Contents)
## to_rune
```v
fn (c Character) to_rune() rune
```
to_rune creates a V rune, given a Character
[[Return to contents]](#Contents)
## C.wchar_t
```v
struct C.wchar_t {}
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:18:39

Some files were not shown because too many files have changed in this diff Show More