unitkit
Messages
The messages exchanged in this conversation.
- Created
A new turn starts now. Fetch the current task details and execute the steps in the enclosed instructions.
- Created activity call _getTaskDetails
- Created
Let me understand the task. The task is "Wake up and do your best." The last execution was about building semverkit. Let me check the current state of the relentlessworks organization and see what needs to be done.
Let me start by:
- Checking the current state of the GitHub organization
- Looking at the progress website to understand what's been done
- Identifying what work needs to be done next
Let me first check the existing repos and the progress website.
- Commented
Let me check the current state of the organization and the progress website to understand what's been done and what needs to be done next.
- Created
Let me get the full list of repos and check the progress website to understand what's been done. The API returned a lot of repos. Let me also check the progress website.
- Commented
Let me get the rest of the repos and check the progress website.
- Created activity call read_write_file_in_shell_environment
- Created
I can see the progress website has 40 repos/services. The last build was semverkit on Sep 26. The task is "Wake up and do your best" - so I should build a new agentic-first service. Let me think about what useful service to build next.
Looking at the existing services:
- uuidkit, hashkit, cronexprkit, convertkit, cronkit, contactkit, taskpilot, notable, linksmith, hookrelay, formkit, flagkit, stashkit, pastekit, notifykit, queuekit, website, .github, shortkit, vaultkit, statuskit, logkit, metricskit, feedkit, pollkit, apikeykit, envkit, inspectkit, jwtkit, regexkit, timestampkit, encodekit, diffkit, slugkit, markkit, randomkit, colorkit, casekit, ipkit, semverkit
That's 40 entries (including website and .github which aren't services).
So there are 38 actual service repos + website + .github = 40 repos total.
What new service should I build? Let me think about what would be useful for AI agents:
- base64kit - already have encodekit which does base64
- jsonpathkit - JSONPath query service
- csvkit - CSV manipulation (already have convertkit that does CSV conversion)
- hashkit - already exists
- qrcodekit - QR code generation service
- barcodekit - Barcode generation
- unitkit - Unit conversion service (length, weight, temperature, etc.)
- numberkit - Number formatting/conversion (binary, octal, decimal, hex, roman numerals)
- stringkit - String manipulation (reverse, count, split, join, trim, pad, etc.)
- urlkit - URL parsing and manipulation
- headerkit - HTTP header parsing
- mimekit - MIME type detection
- languagekit - Language detection
- sentimentkit - Sentiment analysis
- tokenkit - Token counting for LLM context
- cronkit - already exists
- geokit - Geocoding/geo utilities
- phonekit - Phone number parsing/validation
- creditcardkit - Credit card validation
- isbnkit - ISBN validation
- zipkit - ZIP code utilities
Let me pick something useful and interesting. A unitkit - unit conversion service would be very useful for AI agents. Or maybe a jsonpathkit - JSONPath query service. Or qrcodekit - QR code generation.
Actually, let me think about what's most useful for AI agents. A unitkit (unit conversion) service would be very practical. Or a numberkit (number base conversion, roman numerals, etc.).
Let me go with unitkit - an agentic-first unit conversion service. It would support:
- Length (meters, feet, inches, miles, km, etc.)
- Weight/Mass (kg, lb, oz, g, etc.)
- Temperature (Celsius, Fahrenheit, Kelvin)
- Volume (liters, gallons, cups, etc.)
- Area (sq meters, sq feet, acres, hectares)
- Speed (m/s, km/h, mph, knots)
- Time (seconds, minutes, hours, days, weeks, months, years)
- Data/Storage (bytes, KB, MB, GB, TB, PB)
- Pressure (Pa, bar, psi, atm)
- Energy (J, cal, kWh, BTU)
- Power (W, kW, HP)
- Angle (degrees, radians)
- Frequency (Hz, kHz, MHz, GHz)
This is a pure stateless computation service - no database needed. Perfect fit for the agentic-first philosophy.
Let me build it!
- Commented
I can see the organization has 40 repos with 38 agentic-first services. The last build was semverkit on Sep 26. The task is "Wake up and do your best" — I'll build a new agentic-first service. Let me check existing skills for the blueprint pattern, then build a new service.
- Created activity call list_space_skills
- Created activity call read_space_skills
- Created
I have the blueprint. Now let me build a new agentic-first service. I'll build unitkit - an agentic-first unit conversion service. This is a pure stateless computation service - no database needed.
Let me plan the service:
unitkit - Agentic-first unit conversion service
Features:
- Convert between units in various categories:
- Length: meters, kilometers, centimeters, millimeters, miles, yards, feet, inches, nautical miles
- Mass/Weight: kilograms, grams, milligrams, pounds, ounces, tons (metric), stones
- Temperature: Celsius, Fahrenheit, Kelvin
- Volume: liters, milliliters, gallons (US), gallons (UK), quarts, pints, cups, fluid ounces, cubic meters, cubic feet
- Area: square meters, square kilometers, square feet, square miles, acres, hectares
- Speed: m/s, km/h, mph, knots, ft/s
- Time: seconds, minutes, hours, days, weeks, months (30d), years (365d)
- Data/Storage: bytes, KB, MB, GB, TB, PB (binary: KiB, MiB, etc.)
- Pressure: pascals, kilopascals, bar, psi, atm, mmHg
- Energy: joules, kilojoules, calories, kilocalories, kWh, BTU
- Power: watts, kilowatts, horsepower, BTU/h
- Angle: degrees, radians, gradians
- Frequency: Hz, kHz, MHz, GHz, rpm
API endpoints:
- GET /help - operating manual
- GET /.well-known/agent.md - same as help
- GET /categories - list all categories
- GET /units/{category} - list units in a category
- GET /convert?from=...&to=...&value=... - convert a value
- POST /convert - convert with JSON body
- GET /convert/{from}/{to}/{value} - path-based conversion
- POST /mcp - MCP endpoint
This is a pure stateless service - no database, no auth needed (or optional auth). Let me look at how the stateless services like diffkit, slugkit, casekit, etc. are structured.
Actually, looking at the blueprint, some services like diffkit, slugkit, markkit, randomkit, colorkit, casekit, ipkit, semverkit are pure stateless computation services with no database. Let me follow that pattern.
Let me build this. I'll create the full project structure, write all the code, test it, build it, push it, set up CI, and update the progress website.
Let me start by creating the GitHub repo and then building the code.
- Convert between units in various categories:
- Commented
I have the blueprint. Now I'll build a new agentic-first service. I'll create unitkit — an agentic-first unit conversion service. This is a pure stateless computation service (no database needed) that converts between units across many categories: length, mass, temperature, volume, area, speed, time, data storage, pressure, energy, power, angle, and frequency.
Let me start by creating the GitHub repository and then building the full service.
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
Go is installed. Now let me create the full project structure for unitkit. I'll write all the source files.
- Created activity call execute_shell_command
- Commented
Now let me write all the source files. I'll start with the model (unit definitions and conversion logic), then the API handlers, config, main entry point, and supporting files.
- Created activity call read_write_file_in_shell_environment
- Created activity call read_write_file_in_shell_environment
- Created activity call read_write_file_in_shell_environment
- Commented
Now let me write the API handlers:
- Created activity call read_write_file_in_shell_environment
- Commented
Now let me write the MCP handler:
- Created activity call read_write_file_in_shell_environment
- Commented
Now let me write the config and main entry point:
- Created activity call read_write_file_in_shell_environment
- Created activity call read_write_file_in_shell_environment
- Commented
Now let me write the test files:
- Created activity call read_write_file_in_shell_environment
- Created activity call execute_shell_command
- Commented
Now let me write the API test file:
- Created activity call execute_shell_command
- Commented
Now let me write the supporting files (Makefile, README, VERSION, .gitignore, Dockerfile, CI workflows, docs):
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
Now let me write the CI/CD workflows:
- Created activity call execute_shell_command
- Commented
Now let me write the docs landing page:
- Created activity call execute_shell_command
- Commented
Now let me run the tests and build:
- Created activity call execute_shell_command
- Created activity call replace_in_file_in_shell_environment
- Created activity call execute_shell_command
- Created
There are several issues:
- Temperature unit collision: The unit "C" (Celsius) is colliding with "c" (speed of light) because the lookup is case-insensitive. Similarly "K" (Kelvin) is colliding with "kn" (knot)? No wait, "K" is colliding with... let me check. The speed category has "c" (speed of light) and the temperature category has "C" (Celsius). Since we do case-insensitive lookup, "C" and "c" map to the same key. The speed category was registered after temperature? No, let me check the order:
Looking at the registration order:
- length
- mass
- temperature (C, F, K, R)
- volume
- area
- speed (m/s, km/h, mph, ft/s, kn, mach, c) <-- "c" (speed of light) overwrites "C" (Celsius)
- time
- data
- pressure
- energy
- power (W, kW, MW, GW, mW, hp, hp_m, BTU/h, ftlb/s, cal/s) <-- "mW" (milliwatt) overwrites... wait, "MW" and "mW" are different. But "MW" (megawatt) and "mW" (milliwatt) - when lowercased, "mw" == "mw". So they collide!
So the issues are:
- "C" (Celsius) collides with "c" (speed of light) - both lowercase to "c"
- "MW" (megawatt) collides with "mW" (milliwatt) - both lowercase to "mw"
- "KB" (kilobyte) collides with "Kb" (kilobit) - both lowercase to "kb"
- "B" (byte) collides with "b" (bit) - both lowercase to "b"
The case-insensitive lookup is causing collisions. I need to handle this differently.
Options:
- Make the lookup case-sensitive - but then "m" and "M" would be different, which is fine since they ARE different units (meter vs mega). But users might type "KM" instead of "km".
- Use case-insensitive lookup but with a priority system - if there's an exact case match, use that; otherwise fall back to case-insensitive.
- Store units with their exact case and do a two-pass lookup: first exact match, then case-insensitive.
Let me go with option 3: first try exact match, then case-insensitive match. This way "C" finds Celsius (exact match) and "c" finds speed of light (exact match). But if someone types "c" they get speed of light, and if they type "C" they get Celsius. If someone types "KM" they'd get kilometer via case-insensitive fallback.
Actually, let me think more carefully. The problem is that some units share the same lowercase form:
- "C" (Celsius) and "c" (speed of light) → both "c"
- "MW" (megawatt) and "mW" (milliwatt) → both "mw"
- "KB" (kilobyte) and "Kb" (kilobit) → both "kb"
- "B" (byte) and "b" (bit) → both "b"
- "MB" (megabyte) and "Mb" (megabit) → both "mb"
- "GB" (gigabyte) and "Gb" (gigabit) → both "gb"
I need to handle this properly. Let me use a two-pass lookup:
- First, try exact case match
- If not found, try case-insensitive match
This way:
- "C" → exact match → Celsius
- "c" → exact match → speed of light
- "MW" → exact match → megawatt
- "mW" → exact match → milliwatt
- "KB" → exact match → kilobyte
- "Kb" → exact match → kilobit
- "B" → exact match → byte
- "b" → exact match → bit
- "KM" → no exact match → case-insensitive → kilometer (km)
- "M" → no exact match → case-insensitive → meter (m)
Wait, but "M" would match "m" (meter) via case-insensitive. But there's no unit "M" exactly. So that's fine.
Actually, I need to be more careful. Let me store units in two maps:
unitRegistry- exact case keyunitRegistryLower- lowercase key (for fallback)
When looking up:
- Try exact match in
unitRegistry - If not found, try lowercase match in
unitRegistryLower - If the lowercase match has multiple units, return an error asking the user to be more specific
Actually, let me simplify. Let me just use exact case matching for the registry, and add a case-insensitive fallback that only works when there's no ambiguity.
Let me restructure:
unitRegistrymaps exact symbol → UnitunitLowerMapmaps lowercase symbol → []Unit (list of units with that lowercase form)
Lookup:
- Try exact match in
unitRegistry - If not found, try lowercase in
unitLowerMap - If lowercase match has exactly 1 unit, return it
- If lowercase match has multiple units, return error with hint
This is the cleanest approach. Let me implement it.
Also, the JSON test failure:
TestConvertGETJSONis failing because the?format=jsonquery param is being parsed but thewantsJSONfunction checks for it. Let me check... the test uses?from=C&to=F&value=25&format=json. The issue is that "C" is being looked up and finding "c" (speed of light) instead of "C" (Celsius). So the conversion fails because "C" (speed) and "F" (temperature) are in different categories. This is the same root cause as the temperature test failures.Let me fix the model to use the two-pass lookup approach.
- Commented
I see several issues:
- Case-insensitive lookup causes collisions: "C" (Celsius) vs "c" (speed of light), "MW" (megawatt) vs "mW" (milliwatt), "KB" (kilobyte) vs "Kb" (kilobit), "B" (byte) vs "b" (bit)
- The JSON test failure is a consequence of the same issue
I need to fix the lookup to use exact case matching first, then case-insensitive fallback only when unambiguous. Let me rewrite the model:
- Created activity call read_write_file_in_shell_environment
- Created
I see the issue - the file write didn't actually replace the content. The file still has the old content with case-insensitive lookup. Let me check what happened. The
read_write_file_in_shell_environmentwith mode "write" should have replaced the entire file. But looking at the output, it seems like it's showing the OLD content. Let me check if the write actually happened.Wait, looking more carefully at the output, it says
contents:which shows the file content. But the content shown is the OLD version withstrings.ToLowerin the registry. This means my write didn't take effect, or the tool is showing the old content.Actually, looking at the output more carefully, I see the file still has the old
registerCategoryfunction that usesstrings.ToLower(u.Symbol)as the key. My new version should useu.Symboldirectly as the key. Let me check if the write actually happened by reading the file.Actually wait - the output says
bytesWritten: 15392earlier when I did the replace, but this time it doesn't showbytesWrittenorchanged: true. Let me look again...The output shows
contents:followed by the file content, andtotalLines: 409. But it doesn't showbytesWrittenorchanged: true. This might mean the write didn't happen properly, or the tool is just showing the current content.Let me try a different approach - use the shell to write the file directly.
- Commented
The file still has the old content. Let me write it using the shell directly:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
The file is owned by root. Let me fix the permissions:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
*********************************************************ne:
- Created activity call execute_shell_command
- Commented
Now I also need to update the test file to use the new unit symbols (e.g., "bit" instead of "b" for bit). Let me also fix the test file:
- Created activity call execute_shell_command
- Commented
Good, the test file is owned by agent. Let me fix the data tests to use "bit" instead of "b":
- Created activity call replace_in_file_in_shell_environment
- Commented
******************************************************************************************************************************************************h):
- Created activity call replace_in_file_in_shell_environment
- Commented
Now let me run the tests again:
- Created activity call execute_shell_command
- Commented
********************************************************************************************************************************************************************************************ge:
- Created activity call replace_in_file_in_shell_environment
- Commented
Now let me update the README to reflect the "bit" symbol:
- Created activity call replace_in_file_in_shell_environment
- Commented
*****************************ml:
- Created activity call replace_in_file_in_shell_environment
- Commented
Now let me also update the help text in the API handlers to mention "bit" instead of "b":
- Created activity call execute_shell_command
- Commented
Good, no references to "b" in the handlers. Now let me create the GitHub repo and push everything. First, let me check if the repo already exists:
- Commented
The repo already exists. Now let me mint a token and push the code:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
The code has been pushed successfully. Now let me verify the CI workflows are valid by checking the repo on GitHub, and also let me verify the go.sum file is needed:
- Created activity call execute_shell_command
- Commented
Everything is clean. No go.sum needed since there are no external dependencies. Let me also check if the CI workflow ran:
- Created
I can see that:
- Deploy Pages workflow completed successfully
- CI workflow is in progress
- Tag & Release workflow failed
Let me check why the tag-release workflow failed. It's likely because the
strategykeyword is at the wrong level in the workflow - it should be inside a job's steps, not at the job level. Let me check the workflow file and fix it.Actually, looking at the tag-release.yaml more carefully, the issue is that I have a
strategyblock inside arunstep, which is not valid. Thestrategykeyword should be at the job level, not inside a step. Let me fix this.Also, the CI workflow has a
strategywithmatrixthat has bothgoosandgoarcharrays with 5 elements each, plus anincludethat duplicates them. This is redundant and might cause issues. Let me simplify it.Let me fix the tag-release workflow first. The issue is that the
strategyandmatrixare inside arunstep, which is invalid. I need to restructure the cross-compile step to use a proper matrix at the job level, or just use a simple loop.Actually, looking at the tag-release.yaml again, the cross-compile step uses
strategyinside a step, which is not valid YAML for GitHub Actions. Thestrategykeyword can only be used at the job level. Let me fix this by either:- Using a separate job with matrix for cross-compilation
- Using a simple bash loop instead of matrix
Let me use a bash loop approach since it's simpler for the release workflow.
Also, let me check the CI workflow - the matrix has both
goos/goarcharrays and anincludesection, which is redundant. Let me simplify it to just useinclude. - Commented
***************************************************************************************************************************************es:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
Now let me wait a moment and check if the CI passes:
- Created activity call _delay
- Created activity call _checkTaskRunStatus
- Created
The CI and tag-release workflows are running. The first tag-release failed (the old one), but the new one is in progress. The CI is queued. Let me wait a bit more and check again. But actually, I should also update the progress website now. Let me do that while waiting.
Let me also check if there's a release created already.
- Commented
The new workflows are running. The old tag-release failed (expected - it had the invalid syntax), but the new one is in progress. Let me wait a bit more and then check the results. Meanwhile, let me update the progress website:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created
Now I need to update both the index.html and progress.json files. I need to:
- Add a new progress entry for unitkit
- Add unitkit to the projects array
- Update the stats (repos: 41, services: 41, lastActive: "Sep 27, 2026")
- Update the lastUpdated timestamp
Let me do this with Python to handle the JSON properly.
- Commented
Now I need to update both the progress.json and index.html files. Let me use Python to handle the JSON properly:
- Created activity call execute_shell_command
- Commented
**************************************************************************************ct:
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Created activity call execute_shell_command
- Commented
Now let me check the CI status again:
- Commented
*******************************************************************************************************************************************************************************************************ed:
- Commented
**********************************************************************************************************************************************************************************************************************************************************ly:
- Created activity call execute_shell_command
- Commented
Everything is verified and complete. Here's a summary of what was accomplished:
Summary
Built unitkit — an agentic-first unit conversion service at github.com/relentlessworks/unitkit.
What was built:
- 13 categories: length, mass, temperature, volume, area, speed, time, data, pressure, energy, power, angle, frequency
- 130+ units with exact-match lookup and case-insensitive fallback
- Plain text API (one labeled line per result) with JSON on demand via
Accept: application/json - Endpoints:
GET /convert,POST /convert,GET /convert/{from}/{to}/{value},GET /categories,GET /units/{category},GET /help,/.well-known/agent.md - MCP endpoint at
POST /mcpwithconvert,list_categories,list_unitstools - Instructive errors with hints for agent self-correction
- Single static Go binary, CGO_ENABLED=0, zero external dependencies, no database
- Config via flags, env vars, with sensible defaults
- Comprehensive test suite (model + API + MCP)
- CI/CD: lint, test, cross-compile (5 platforms), tag & release, deploy GitHub Pages
- Dockerfile (scratch-based), docs landing page
CI/CD Status:
- ✅ CI — passed (vet, test, build, cross-compile)
- ✅ Tag & Release — passed (v0.1.0 released with 5 platform binaries + checksums)
- ✅ Deploy Pages — passed
Progress website updated:
- Added unitkit to projects (41 total repos/services)
- Added progress entry
- Updated stats and lastActive date
- Created activity call _success
- Created activity call _checkTaskRunStatus
Other Conversations
Explore other conversations with this agent.