mirror of
https://github.com/seemueller-io/sumpin.git
synced 2025-09-08 22:56:46 +00:00
add code
This commit is contained in:
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/target
|
||||||
|
.idea
|
||||||
|
Cargo.lock
|
||||||
|
*.iml
|
||||||
|
node_modules
|
||||||
|
bun.lockb
|
||||||
|
.junie
|
||||||
|
project
|
||||||
|
.env
|
||||||
|
|
||||||
|
|
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "sumpin"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
240
bun.lock
Normal file
240
bun.lock
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "sumpin",
|
||||||
|
"dependencies": {
|
||||||
|
"@openai/agents": "^0.0.11",
|
||||||
|
"mobx": "^6.13.7",
|
||||||
|
"mobx-state-tree": "^7.0.2",
|
||||||
|
"openai": "^5.9.0",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
|
"zod": "<=3.25.67",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.15.1", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-W/XlN9c528yYn+9MQkVjxiTPgPxoxt+oczfjHBDsJx0+59+O7B75Zhsp0B16Xbwbz8ANISDajh6+V7nIcPMc5w=="],
|
||||||
|
|
||||||
|
"@openai/agents": ["@openai/agents@0.0.11", "", { "dependencies": { "@openai/agents-core": "0.0.11", "@openai/agents-openai": "0.0.11", "@openai/agents-realtime": "0.0.11", "debug": "^4.4.0", "openai": "^5.0.1" } }, "sha512-MYSuQ0PptjryTb/BzrqoZB+cajv/p31uF42uXeqkI3s9PihqRttnQBJ1YCTJS/xQCl4f5R9cIradh/o5PpbDkA=="],
|
||||||
|
|
||||||
|
"@openai/agents-core": ["@openai/agents-core@0.0.11", "", { "dependencies": { "@openai/zod": "npm:zod@3.25.40 - 3.25.67", "debug": "^4.4.0", "openai": "^5.0.1" }, "optionalDependencies": { "@modelcontextprotocol/sdk": "^1.12.0" }, "peerDependencies": { "zod": "3.25.40 - 3.25.67" }, "optionalPeers": ["zod"] }, "sha512-kMG/B620fsFAwUe/ounmXty4FuAmWbMWgql4z/gCoER3S6h5tBqNTxffN0MAOFHV3EuPLiqTxA0kGiSdTpDwyA=="],
|
||||||
|
|
||||||
|
"@openai/agents-openai": ["@openai/agents-openai@0.0.11", "", { "dependencies": { "@openai/agents-core": "0.0.11", "@openai/zod": "npm:zod@3.25.40 - 3.25.67", "debug": "^4.4.0", "openai": "^5.0.1" } }, "sha512-gqVVDfyD0UYYBkc4kPJgbWzFzayKCKQBHMKHnbMsReZ8/nqHKGEd/hjBiqAZGqDW0BTKNaGfzGB8XAiLWWipnw=="],
|
||||||
|
|
||||||
|
"@openai/agents-realtime": ["@openai/agents-realtime@0.0.11", "", { "dependencies": { "@openai/agents-core": "0.0.11", "@openai/zod": "npm:zod@3.25.40 - 3.25.67", "@types/ws": "^8.18.1", "debug": "^4.4.0", "ws": "^8.18.1" } }, "sha512-gVdrKri0dPBOJfsQR6m9rdpBscRZK/efc1zLKqOA2mfmaL0RxI2/LvnyXbwrDGHQ6GEbovULkbWWQ9D4nUafow=="],
|
||||||
|
|
||||||
|
"@openai/zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="],
|
||||||
|
|
||||||
|
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@24.0.13", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ=="],
|
||||||
|
|
||||||
|
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||||
|
|
||||||
|
"@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="],
|
||||||
|
|
||||||
|
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||||
|
|
||||||
|
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||||
|
|
||||||
|
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||||
|
|
||||||
|
"body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||||
|
|
||||||
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||||
|
|
||||||
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||||
|
|
||||||
|
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||||
|
|
||||||
|
"content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="],
|
||||||
|
|
||||||
|
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||||
|
|
||||||
|
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||||
|
|
||||||
|
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||||
|
|
||||||
|
"cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="],
|
||||||
|
|
||||||
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
|
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||||
|
|
||||||
|
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||||
|
|
||||||
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
|
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||||
|
|
||||||
|
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||||
|
|
||||||
|
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||||
|
|
||||||
|
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
|
|
||||||
|
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||||
|
|
||||||
|
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
||||||
|
|
||||||
|
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
||||||
|
|
||||||
|
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
||||||
|
|
||||||
|
"eventsource-parser": ["eventsource-parser@3.0.3", "", {}, "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA=="],
|
||||||
|
|
||||||
|
"express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="],
|
||||||
|
|
||||||
|
"express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="],
|
||||||
|
|
||||||
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||||
|
|
||||||
|
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||||
|
|
||||||
|
"finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="],
|
||||||
|
|
||||||
|
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
||||||
|
|
||||||
|
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
||||||
|
|
||||||
|
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||||
|
|
||||||
|
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||||
|
|
||||||
|
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||||
|
|
||||||
|
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||||
|
|
||||||
|
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||||
|
|
||||||
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
|
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
|
||||||
|
|
||||||
|
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||||
|
|
||||||
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||||
|
|
||||||
|
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
||||||
|
|
||||||
|
"is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
||||||
|
|
||||||
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
|
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||||
|
|
||||||
|
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||||
|
|
||||||
|
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||||
|
|
||||||
|
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
||||||
|
|
||||||
|
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||||
|
|
||||||
|
"mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="],
|
||||||
|
|
||||||
|
"mobx": ["mobx@6.13.7", "", {}, "sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g=="],
|
||||||
|
|
||||||
|
"mobx-state-tree": ["mobx-state-tree@7.0.2", "", { "dependencies": { "ts-essentials": "^9.4.1" }, "peerDependencies": { "mobx": "^6.3.0" } }, "sha512-Qmqgo2Ho1/JRTquo0EWw0ZA/k4wTUNPMIBg98ALGN1V/0Gupic7dg4GDYUhNbiLsYHpp48VgpaCDpDIKV+jNkQ=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||||
|
|
||||||
|
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||||
|
|
||||||
|
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||||
|
|
||||||
|
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
||||||
|
|
||||||
|
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||||
|
|
||||||
|
"openai": ["openai@5.9.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-cmLC0pfqLLhBGxE4aZPyRPjydgYCncppV2ClQkKmW79hNjCvmzkfhz8rN5/YVDmjVQlFV+UsF1JIuNjNgeagyQ=="],
|
||||||
|
|
||||||
|
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
||||||
|
|
||||||
|
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="],
|
||||||
|
|
||||||
|
"pkce-challenge": ["pkce-challenge@5.0.0", "", {}, "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ=="],
|
||||||
|
|
||||||
|
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||||
|
|
||||||
|
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||||
|
|
||||||
|
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||||
|
|
||||||
|
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
||||||
|
|
||||||
|
"raw-body": ["raw-body@3.0.0", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.6.3", "unpipe": "1.0.0" } }, "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g=="],
|
||||||
|
|
||||||
|
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
||||||
|
|
||||||
|
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||||
|
|
||||||
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
|
"send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="],
|
||||||
|
|
||||||
|
"serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="],
|
||||||
|
|
||||||
|
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||||
|
|
||||||
|
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
|
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||||
|
|
||||||
|
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
||||||
|
|
||||||
|
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||||
|
|
||||||
|
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||||
|
|
||||||
|
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||||
|
|
||||||
|
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||||
|
|
||||||
|
"ts-essentials": ["ts-essentials@9.4.2", "", { "peerDependencies": { "typescript": ">=4.1.0" }, "optionalPeers": ["typescript"] }, "sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ=="],
|
||||||
|
|
||||||
|
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||||
|
|
||||||
|
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||||
|
|
||||||
|
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||||
|
|
||||||
|
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
|
||||||
|
|
||||||
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||||
|
|
||||||
|
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
|
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||||
|
|
||||||
|
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
|
"zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="],
|
||||||
|
|
||||||
|
"zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="],
|
||||||
|
|
||||||
|
"http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
|
||||||
|
}
|
||||||
|
}
|
332
cli.ts
Normal file
332
cli.ts
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sumpin CLI - Professional Hierarchy Generator
|
||||||
|
*
|
||||||
|
* A command-line interface for generating professional hierarchies from natural language specifications.
|
||||||
|
* Leverages the existing hierarchy generation infrastructure to provide a clean, professional CLI experience.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { parseArgs } from 'util';
|
||||||
|
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
||||||
|
import { join, resolve } from 'path';
|
||||||
|
import { generateHierarchy } from './generate-template';
|
||||||
|
import HierarchyAgent from './lib/agent-wrapper';
|
||||||
|
|
||||||
|
const CLI_VERSION = '1.0.0';
|
||||||
|
const DEFAULT_OUTPUT_DIR = './output';
|
||||||
|
|
||||||
|
interface CLIOptions {
|
||||||
|
help?: boolean;
|
||||||
|
version?: boolean;
|
||||||
|
output?: string;
|
||||||
|
format?: 'json' | 'typescript' | 'both';
|
||||||
|
complexity?: 'simple' | 'medium' | 'complex';
|
||||||
|
hierarchyVersion?: 'v1' | 'v2';
|
||||||
|
stream?: boolean;
|
||||||
|
quiet?: boolean;
|
||||||
|
skills?: boolean;
|
||||||
|
tools?: boolean;
|
||||||
|
examples?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HELP_TEXT = `
|
||||||
|
Sumpin CLI v${CLI_VERSION} - Professional Hierarchy Generator
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
bun cli.ts [OPTIONS] "<natural language specification>"
|
||||||
|
|
||||||
|
DESCRIPTION:
|
||||||
|
Generate professional hierarchies from natural language descriptions.
|
||||||
|
Supports both simple JSON output and full TypeScript code generation.
|
||||||
|
|
||||||
|
ARGUMENTS:
|
||||||
|
specification Natural language description of the hierarchy to generate
|
||||||
|
Example: "Create a healthcare hierarchy for mental health services"
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-h, --help Show this help message
|
||||||
|
-v, --version Show version information
|
||||||
|
-o, --output DIR Output directory (default: ./output)
|
||||||
|
-f, --format FORMAT Output format: json, typescript, both (default: json)
|
||||||
|
-c, --complexity LEVEL Complexity level: simple, medium, complex (default: medium)
|
||||||
|
--hierarchy-version VER Hierarchy version: v1, v2 (default: v2)
|
||||||
|
--stream Enable streaming output for real-time feedback
|
||||||
|
--quiet Suppress progress messages
|
||||||
|
--skills Include skills and competencies (default: true)
|
||||||
|
--tools Include tools and technologies (default: true)
|
||||||
|
--examples Include practical examples (default: true)
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
# Basic usage - generate JSON hierarchy
|
||||||
|
bun cli.ts "Create a technology hierarchy for AI development"
|
||||||
|
|
||||||
|
# Generate TypeScript code with streaming
|
||||||
|
bun cli.ts --format typescript --stream "Healthcare hierarchy for emergency medicine"
|
||||||
|
|
||||||
|
# Complex v1 hierarchy with custom output directory
|
||||||
|
bun cli.ts -o ./my-hierarchies -c complex --hierarchy-version v1 "Finance hierarchy for investment banking"
|
||||||
|
|
||||||
|
# Generate both formats quietly
|
||||||
|
bun cli.ts --format both --quiet "Education hierarchy for online learning platforms"
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
Generated files will be saved to the specified output directory with descriptive names.
|
||||||
|
JSON format: Creates .json files with the hierarchy data
|
||||||
|
TypeScript format: Creates .ts files with executable TypeScript code
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Parse command line arguments
|
||||||
|
function parseCliArgs(): { options: CLIOptions; specification: string } {
|
||||||
|
const { values, positionals } = parseArgs({
|
||||||
|
args: process.argv.slice(2),
|
||||||
|
options: {
|
||||||
|
help: { type: 'boolean', short: 'h' },
|
||||||
|
version: { type: 'boolean', short: 'v' },
|
||||||
|
output: { type: 'string', short: 'o' },
|
||||||
|
format: { type: 'string', short: 'f' },
|
||||||
|
complexity: { type: 'string', short: 'c' },
|
||||||
|
'hierarchy-version': { type: 'string' },
|
||||||
|
stream: { type: 'boolean' },
|
||||||
|
quiet: { type: 'boolean' },
|
||||||
|
skills: { type: 'boolean' },
|
||||||
|
tools: { type: 'boolean' },
|
||||||
|
examples: { type: 'boolean' },
|
||||||
|
},
|
||||||
|
allowPositionals: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const options: CLIOptions = {
|
||||||
|
help: values.help,
|
||||||
|
version: values.version,
|
||||||
|
output: values.output || DEFAULT_OUTPUT_DIR,
|
||||||
|
format: (values.format as any) || 'json',
|
||||||
|
complexity: (values.complexity as any) || 'medium',
|
||||||
|
hierarchyVersion: (values['hierarchy-version'] as any) || 'v2',
|
||||||
|
stream: values.stream || false,
|
||||||
|
quiet: values.quiet || false,
|
||||||
|
skills: values.skills !== false,
|
||||||
|
tools: values.tools !== false,
|
||||||
|
examples: values.examples !== false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const specification = positionals.join(' ');
|
||||||
|
|
||||||
|
return { options, specification };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate CLI options
|
||||||
|
function validateOptions(options: CLIOptions, specification: string): void {
|
||||||
|
if (!['json', 'typescript', 'both'].includes(options.format!)) {
|
||||||
|
console.error('❌ Error: Invalid format. Must be one of: json, typescript, both');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!['simple', 'medium', 'complex'].includes(options.complexity!)) {
|
||||||
|
console.error('❌ Error: Invalid complexity. Must be one of: simple, medium, complex');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!['v1', 'v2'].includes(options.hierarchyVersion!)) {
|
||||||
|
console.error('❌ Error: Invalid hierarchy version. Must be one of: v1, v2');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!specification.trim()) {
|
||||||
|
console.error('❌ Error: Natural language specification is required');
|
||||||
|
console.error('Use --help for usage information');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate filename from specification
|
||||||
|
function generateFilename(specification: string, format: string): string {
|
||||||
|
const cleanSpec = specification
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9\s]/g, '')
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.substring(0, 50);
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, '');
|
||||||
|
return `hierarchy-${cleanSpec}-${timestamp}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate hierarchy using the simple JSON approach
|
||||||
|
async function generateJsonHierarchy(specification: string, options: CLIOptions): Promise<any> {
|
||||||
|
if (!options.quiet) {
|
||||||
|
console.log('🔄 Generating hierarchy using JSON approach...');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hierarchy = await generateHierarchy(specification);
|
||||||
|
return hierarchy.toJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate hierarchy using the agent-based TypeScript approach
|
||||||
|
async function generateTypescriptHierarchy(specification: string, options: CLIOptions): Promise<string> {
|
||||||
|
if (!options.quiet) {
|
||||||
|
console.log('🔄 Generating hierarchy using TypeScript agent approach...');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hierarchyAgent = new HierarchyAgent({
|
||||||
|
name: 'CLI Hierarchy Generator',
|
||||||
|
instructions: `Generate professional hierarchy TypeScript code based on user specifications.
|
||||||
|
Focus on creating clean, implementable code that demonstrates real-world organizational structures.`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const generationOptions = {
|
||||||
|
domain: extractDomain(specification),
|
||||||
|
version: options.hierarchyVersion!,
|
||||||
|
complexity: options.complexity!,
|
||||||
|
includeSkills: options.skills!,
|
||||||
|
includeTools: options.tools!,
|
||||||
|
includeExamples: options.examples!,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.stream) {
|
||||||
|
return await hierarchyAgent.generateHierarchyWithStreaming(
|
||||||
|
generationOptions,
|
||||||
|
options.quiet ? undefined : (event) => {
|
||||||
|
if (event.type === 'raw_model_stream_event' && event.delta?.content) {
|
||||||
|
process.stdout.write('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).then(result => result.content);
|
||||||
|
} else {
|
||||||
|
const result = await hierarchyAgent.generateHierarchy(generationOptions);
|
||||||
|
return result.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract domain from specification (simple heuristic)
|
||||||
|
function extractDomain(specification: string): string {
|
||||||
|
const words = specification.toLowerCase().split(/\s+/);
|
||||||
|
|
||||||
|
// Look for domain keywords
|
||||||
|
const domainKeywords = [
|
||||||
|
'healthcare', 'technology', 'finance', 'education', 'manufacturing',
|
||||||
|
'retail', 'consulting', 'media', 'logistics', 'legal', 'construction',
|
||||||
|
'hospitality', 'automotive', 'aerospace', 'energy', 'agriculture'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const keyword of domainKeywords) {
|
||||||
|
if (words.some(word => word.includes(keyword))) {
|
||||||
|
return keyword;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: use first meaningful word
|
||||||
|
const meaningfulWords = words.filter(word =>
|
||||||
|
word.length > 3 &&
|
||||||
|
!['create', 'generate', 'build', 'make', 'hierarchy', 'for', 'the', 'and', 'with'].includes(word)
|
||||||
|
);
|
||||||
|
|
||||||
|
return meaningfulWords[0] || 'general';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save output to files
|
||||||
|
async function saveOutput(
|
||||||
|
content: any,
|
||||||
|
filename: string,
|
||||||
|
format: string,
|
||||||
|
outputDir: string,
|
||||||
|
quiet: boolean
|
||||||
|
): Promise<void> {
|
||||||
|
// Ensure output directory exists
|
||||||
|
if (!existsSync(outputDir)) {
|
||||||
|
mkdirSync(outputDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputPath = resolve(outputDir);
|
||||||
|
|
||||||
|
if (format === 'json' || format === 'both') {
|
||||||
|
const jsonFile = join(outputPath, `${filename}.json`);
|
||||||
|
const jsonContent = typeof content === 'string' ? content : JSON.stringify(content, null, 2);
|
||||||
|
writeFileSync(jsonFile, jsonContent);
|
||||||
|
if (!quiet) {
|
||||||
|
console.log(`✅ JSON hierarchy saved: ${jsonFile}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'typescript' || format === 'both') {
|
||||||
|
const tsFile = join(outputPath, `${filename}.ts`);
|
||||||
|
const tsContent = typeof content === 'string' ? content : `// Generated hierarchy\nexport const hierarchy = ${JSON.stringify(content, null, 2)};`;
|
||||||
|
writeFileSync(tsFile, tsContent);
|
||||||
|
if (!quiet) {
|
||||||
|
console.log(`✅ TypeScript hierarchy saved: ${tsFile}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main CLI function
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const { options, specification } = parseCliArgs();
|
||||||
|
|
||||||
|
// Handle help and version
|
||||||
|
if (options.help) {
|
||||||
|
console.log(HELP_TEXT);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.version) {
|
||||||
|
console.log(`Sumpin CLI v${CLI_VERSION}`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate options
|
||||||
|
validateOptions(options, specification);
|
||||||
|
|
||||||
|
if (!options.quiet) {
|
||||||
|
console.log(`🚀 Sumpin CLI v${CLI_VERSION} - Professional Hierarchy Generator`);
|
||||||
|
console.log(`📝 Specification: "${specification}"`);
|
||||||
|
console.log(`⚙️ Configuration:`);
|
||||||
|
console.log(` Format: ${options.format}`);
|
||||||
|
console.log(` Complexity: ${options.complexity}`);
|
||||||
|
console.log(` Version: ${options.hierarchyVersion}`);
|
||||||
|
console.log(` Output: ${options.output}`);
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = generateFilename(specification, options.format!);
|
||||||
|
let content: any;
|
||||||
|
|
||||||
|
// Generate based on format preference
|
||||||
|
if (options.format === 'json') {
|
||||||
|
content = await generateJsonHierarchy(specification, options);
|
||||||
|
} else if (options.format === 'typescript') {
|
||||||
|
content = await generateTypescriptHierarchy(specification, options);
|
||||||
|
} else if (options.format === 'both') {
|
||||||
|
// Generate both formats
|
||||||
|
const jsonContent = await generateJsonHierarchy(specification, options);
|
||||||
|
const tsContent = await generateTypescriptHierarchy(specification, options);
|
||||||
|
|
||||||
|
await saveOutput(jsonContent, filename, 'json', options.output!, options.quiet!);
|
||||||
|
await saveOutput(tsContent, filename, 'typescript', options.output!, options.quiet!);
|
||||||
|
|
||||||
|
if (!options.quiet) {
|
||||||
|
console.log('\n🎉 Hierarchy generation complete!');
|
||||||
|
console.log(`📁 Files saved to: ${resolve(options.output!)}`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save single format output
|
||||||
|
await saveOutput(content, filename, options.format!, options.output!, options.quiet!);
|
||||||
|
|
||||||
|
if (!options.quiet) {
|
||||||
|
console.log('\n🎉 Hierarchy generation complete!');
|
||||||
|
console.log(`📁 Files saved to: ${resolve(options.output!)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error:', error instanceof Error ? error.message : String(error));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run CLI if this file is executed directly
|
||||||
|
if (import.meta.main) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
||||||
|
export { main as runCLI };
|
65
examples/README.md
Normal file
65
examples/README.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Examples Directory
|
||||||
|
|
||||||
|
This directory contains comprehensive examples demonstrating how to use both versions of the professional hierarchy models.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- `v1/` - Examples for the simpler 4-layer hierarchy model (Domain → Specialization → Role → Responsibility)
|
||||||
|
- `v2/` - Examples for the advanced 6-layer hierarchy model (Domain → Industry → Profession → Field → Role → Task)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Make sure you have the required dependencies installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
For v1 and v2 examples, you'll also need:
|
||||||
|
```bash
|
||||||
|
bun add mobx-state-tree mobx uuid
|
||||||
|
bun add -d @types/uuid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Examples
|
||||||
|
|
||||||
|
Each example can be run independently using Bun:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run v1 examples
|
||||||
|
bun run examples/v1/healthcare-example.ts
|
||||||
|
bun run examples/v1/technology-example.ts
|
||||||
|
|
||||||
|
# Run v2 examples
|
||||||
|
bun run examples/v2/software-company-example.ts
|
||||||
|
bun run examples/v2/healthcare-system-example.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Examples
|
||||||
|
|
||||||
|
You can also run the test files to see the examples in action:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test v1 examples
|
||||||
|
bun test examples/v1/
|
||||||
|
|
||||||
|
# Test v2 examples
|
||||||
|
bun test examples/v2/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Scenarios
|
||||||
|
|
||||||
|
### V1 Examples (4-layer hierarchy)
|
||||||
|
- **Healthcare Example**: Models medical professionals with specializations, roles, and responsibilities
|
||||||
|
- **Technology Example**: Models software engineering domain with various specializations
|
||||||
|
|
||||||
|
### V2 Examples (6-layer hierarchy)
|
||||||
|
- **Software Company Example**: Complete modeling of a tech company's professional structure
|
||||||
|
- **Healthcare System Example**: Comprehensive healthcare organization modeling
|
||||||
|
|
||||||
|
Each example demonstrates:
|
||||||
|
- Creating and structuring hierarchies
|
||||||
|
- Adding attributes/skills/tools
|
||||||
|
- CRUD operations
|
||||||
|
- Querying and traversing the hierarchy
|
||||||
|
- Real-world use cases and best practices
|
349
examples/v1/healthcare-example.ts
Normal file
349
examples/v1/healthcare-example.ts
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
import { ProfessionModel, Domain, Specialization, Role, Responsibility, Attribute } from "../../lib/v1";
|
||||||
|
|
||||||
|
console.log("=== Healthcare Professional Hierarchy Example (V1) ===\n");
|
||||||
|
|
||||||
|
const professionModel = ProfessionModel.create({
|
||||||
|
domains: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the Healthcare domain
|
||||||
|
const healthcareDomain = Domain.create({
|
||||||
|
name: "Healthcare",
|
||||||
|
description: "Medical and health services domain",
|
||||||
|
specializations: [],
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Medical Ethics",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Understanding of medical ethics and patient care principles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Communication",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Effective communication with patients and colleagues"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Electronic Health Records",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Proficiency with EHR systems"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add specializations to Healthcare domain
|
||||||
|
const cardiology = Specialization.create({
|
||||||
|
name: "Cardiology",
|
||||||
|
focus: "Heart and cardiovascular system disorders",
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Cardiac Catheterization",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Performing cardiac catheterization procedures"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ECG Interpretation",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Reading and interpreting electrocardiograms"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Echocardiogram Machine",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Operating echocardiogram equipment"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const pediatrics = Specialization.create({
|
||||||
|
name: "Pediatrics",
|
||||||
|
focus: "Medical care of infants, children, and adolescents",
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Child Psychology",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Understanding child development and psychology"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Vaccination Protocols",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Knowledge of pediatric vaccination schedules"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pediatric Stethoscope",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Specialized stethoscope for children"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create roles for Cardiology
|
||||||
|
const cardiologist = Role.create({
|
||||||
|
title: "Cardiologist",
|
||||||
|
seniority: "Senior",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Board Certification",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Board certified in cardiology"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Surgical Skills",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Advanced surgical techniques for cardiac procedures"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const cardiacNurse = Role.create({
|
||||||
|
title: "Cardiac Nurse",
|
||||||
|
seniority: "Mid",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Critical Care Experience",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Experience in critical care environments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Medication Administration",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Safe administration of cardiac medications"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Cardiologist
|
||||||
|
const diagnosisResponsibility = Responsibility.create({
|
||||||
|
title: "Cardiac Diagnosis",
|
||||||
|
outcome: "Accurate diagnosis of cardiovascular conditions",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Diagnostic Imaging",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Interpreting cardiac imaging studies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Clinical Assessment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Comprehensive cardiovascular examination"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const treatmentPlanningResponsibility = Responsibility.create({
|
||||||
|
title: "Treatment Planning",
|
||||||
|
outcome: "Comprehensive treatment plans for cardiac patients",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Evidence-Based Medicine",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Applying current research to treatment decisions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Risk Assessment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Evaluating patient risk factors"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Cardiac Nurse
|
||||||
|
const patientMonitoringResponsibility = Responsibility.create({
|
||||||
|
title: "Patient Monitoring",
|
||||||
|
outcome: "Continuous monitoring of cardiac patients' vital signs and condition",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Telemetry Monitoring",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Monitoring cardiac rhythms via telemetry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cardiac Monitor",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Operating cardiac monitoring equipment"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create roles for Pediatrics
|
||||||
|
const pediatrician = Role.create({
|
||||||
|
title: "Pediatrician",
|
||||||
|
seniority: "Senior",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Pediatric Board Certification",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Board certified in pediatrics"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Developmental Assessment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Assessing child development milestones"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const pediatricNurse = Role.create({
|
||||||
|
title: "Pediatric Nurse",
|
||||||
|
seniority: "Mid",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Pediatric Nursing Certification",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Certified in pediatric nursing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Family Communication",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Communicating effectively with children and families"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Pediatrician
|
||||||
|
const wellChildExamResponsibility = Responsibility.create({
|
||||||
|
title: "Well-Child Examinations",
|
||||||
|
outcome: "Regular health assessments and preventive care for children",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Growth Assessment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Evaluating child growth patterns"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Immunization Knowledge",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Current knowledge of vaccination schedules"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const developmentalScreeningResponsibility = Responsibility.create({
|
||||||
|
title: "Developmental Screening",
|
||||||
|
outcome: "Early identification of developmental delays or disorders",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Screening Tools",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Standardized developmental screening instruments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Behavioral Assessment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Assessing child behavior and development"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assemble the hierarchy
|
||||||
|
cardiologist.responsibilities.push(diagnosisResponsibility, treatmentPlanningResponsibility);
|
||||||
|
cardiacNurse.responsibilities.push(patientMonitoringResponsibility);
|
||||||
|
pediatrician.responsibilities.push(wellChildExamResponsibility, developmentalScreeningResponsibility);
|
||||||
|
|
||||||
|
cardiology.roles.push(cardiologist, cardiacNurse);
|
||||||
|
pediatrics.roles.push(pediatrician, pediatricNurse);
|
||||||
|
|
||||||
|
healthcareDomain.specializations.push(cardiology, pediatrics);
|
||||||
|
professionModel.domains.push(healthcareDomain);
|
||||||
|
|
||||||
|
// Demonstrate the hierarchy
|
||||||
|
console.log("🏥 Healthcare Domain Structure:");
|
||||||
|
console.log(`Domain: ${healthcareDomain.name}`);
|
||||||
|
console.log(`Description: ${healthcareDomain.description}`);
|
||||||
|
console.log(`Core Attributes: ${healthcareDomain.coreAttributes.length}`);
|
||||||
|
|
||||||
|
healthcareDomain.coreAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\nSpecializations: ${healthcareDomain.specializations.length}`);
|
||||||
|
|
||||||
|
healthcareDomain.specializations.forEach(spec => {
|
||||||
|
console.log(`\n📋 ${spec.name}`);
|
||||||
|
console.log(` Focus: ${spec.focus}`);
|
||||||
|
console.log(` Core Attributes: ${spec.coreAttributes.length}`);
|
||||||
|
|
||||||
|
spec.coreAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(` Roles: ${spec.roles.length}`);
|
||||||
|
|
||||||
|
spec.roles.forEach(role => {
|
||||||
|
console.log(`\n 👨⚕️ ${role.title} (${role.seniority} Level)`);
|
||||||
|
console.log(` Required Attributes: ${role.requiredAttributes.length}`);
|
||||||
|
|
||||||
|
role.requiredAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(` Responsibilities: ${role.responsibilities.length}`);
|
||||||
|
|
||||||
|
role.responsibilities.forEach(resp => {
|
||||||
|
console.log(`\n 📝 ${resp.title}`);
|
||||||
|
console.log(` Outcome: ${resp.outcome}`);
|
||||||
|
console.log(` Required Attributes: ${resp.requiredAttributes.length}`);
|
||||||
|
|
||||||
|
resp.requiredAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Demonstrate querying capabilities
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("🔍 QUERYING EXAMPLES");
|
||||||
|
console.log("=".repeat(60));
|
||||||
|
|
||||||
|
// Find all skills across the domain
|
||||||
|
const allSkills = healthcareDomain.specializations
|
||||||
|
.flatMap(spec => [
|
||||||
|
...spec.coreAttributes.filter(attr => attr.type === "Skill"),
|
||||||
|
...spec.roles.flatMap(role => [
|
||||||
|
...role.requiredAttributes.filter(attr => attr.type === "Skill"),
|
||||||
|
...role.responsibilities.flatMap(resp =>
|
||||||
|
resp.requiredAttributes.filter(attr => attr.type === "Skill")
|
||||||
|
)
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log(`\n💪 All Skills in Healthcare Domain (${allSkills.length}):`);
|
||||||
|
allSkills.forEach(skill => {
|
||||||
|
console.log(` - ${skill.name}: ${skill.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find all tools
|
||||||
|
const allTools = healthcareDomain.specializations
|
||||||
|
.flatMap(spec => [
|
||||||
|
...spec.coreAttributes.filter(attr => attr.type === "Tool"),
|
||||||
|
...spec.roles.flatMap(role => [
|
||||||
|
...role.requiredAttributes.filter(attr => attr.type === "Tool"),
|
||||||
|
...role.responsibilities.flatMap(resp =>
|
||||||
|
resp.requiredAttributes.filter(attr => attr.type === "Tool")
|
||||||
|
)
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log(`\n🛠️ All Tools in Healthcare Domain (${allTools.length}):`);
|
||||||
|
allTools.forEach(tool => {
|
||||||
|
console.log(` - ${tool.name}: ${tool.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find all senior-level roles
|
||||||
|
const seniorRoles = healthcareDomain.specializations
|
||||||
|
.flatMap(spec => spec.roles)
|
||||||
|
.filter(role => role.seniority === "Senior");
|
||||||
|
|
||||||
|
console.log(`\n🎖️ Senior-Level Roles (${seniorRoles.length}):`);
|
||||||
|
seniorRoles.forEach(role => {
|
||||||
|
console.log(` - ${role.title}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("✅ Healthcare example completed successfully!");
|
||||||
|
console.log("=".repeat(60));
|
531
examples/v1/technology-example.ts
Normal file
531
examples/v1/technology-example.ts
Normal file
@@ -0,0 +1,531 @@
|
|||||||
|
import { ProfessionModel, Domain, Specialization, Role, Responsibility, Attribute } from "../../lib/v1";
|
||||||
|
|
||||||
|
console.log("=== Technology Professional Hierarchy Example (V1) ===\n");
|
||||||
|
|
||||||
|
const professionModel = ProfessionModel.create({
|
||||||
|
domains: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the Technology domain
|
||||||
|
const technologyDomain = Domain.create({
|
||||||
|
name: "Technology",
|
||||||
|
description: "Software development and technology services domain",
|
||||||
|
specializations: [],
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Problem Solving",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Analytical thinking and systematic problem-solving approach"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Version Control",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Proficiency with Git and version control systems"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Continuous Learning",
|
||||||
|
type: "Trait",
|
||||||
|
description: "Commitment to staying current with technology trends"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Agile Methodology",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Understanding of Agile/Scrum development processes"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Web Development specialization
|
||||||
|
const webDevelopment = Specialization.create({
|
||||||
|
name: "Web Development",
|
||||||
|
focus: "Building web applications and websites",
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "HTML/CSS",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Markup and styling for web interfaces"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JavaScript",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Client-side and server-side JavaScript programming"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Web Browser DevTools",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Browser developer tools for debugging and optimization"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Responsive Design",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Creating mobile-friendly and adaptive layouts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Data Science specialization
|
||||||
|
const dataScience = Specialization.create({
|
||||||
|
name: "Data Science",
|
||||||
|
focus: "Extracting insights from data using statistical and machine learning methods",
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Statistical Analysis",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Statistical methods and hypothesis testing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python/R",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Programming languages for data analysis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jupyter Notebooks",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Interactive development environment for data science"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Data Visualization",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Creating meaningful visual representations of data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Mobile Development specialization
|
||||||
|
const mobileDevelopment = Specialization.create({
|
||||||
|
name: "Mobile Development",
|
||||||
|
focus: "Building native and cross-platform mobile applications",
|
||||||
|
coreAttributes: [
|
||||||
|
{
|
||||||
|
name: "Mobile UI/UX",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Designing user interfaces for mobile devices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "App Store Guidelines",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Understanding platform-specific app store requirements"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mobile Testing Frameworks",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Tools for testing mobile applications"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create roles for Web Development
|
||||||
|
const frontendDeveloper = Role.create({
|
||||||
|
title: "Frontend Developer",
|
||||||
|
seniority: "Mid",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "React/Vue/Angular",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Modern frontend frameworks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cross-browser Compatibility",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Ensuring consistent behavior across different browsers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Performance Optimization",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Optimizing web application performance"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const fullStackDeveloper = Role.create({
|
||||||
|
title: "Full Stack Developer",
|
||||||
|
seniority: "Senior",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Backend Development",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Server-side programming and API development"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Database Design",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Designing and optimizing database schemas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cloud Platforms",
|
||||||
|
type: "Tool",
|
||||||
|
description: "AWS, Azure, or Google Cloud Platform"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create roles for Data Science
|
||||||
|
const dataAnalyst = Role.create({
|
||||||
|
title: "Data Analyst",
|
||||||
|
seniority: "Junior",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "SQL",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Database querying and data manipulation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Excel/Spreadsheets",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Advanced spreadsheet analysis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Business Intelligence Tools",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Tableau, Power BI, or similar BI tools"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const machineLearningEngineer = Role.create({
|
||||||
|
title: "Machine Learning Engineer",
|
||||||
|
seniority: "Senior",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Machine Learning Algorithms",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Understanding of ML algorithms and their applications"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Model Deployment",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Deploying ML models to production environments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TensorFlow/PyTorch",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Deep learning frameworks"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create roles for Mobile Development
|
||||||
|
const iosDeveloper = Role.create({
|
||||||
|
title: "iOS Developer",
|
||||||
|
seniority: "Mid",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Swift/Objective-C",
|
||||||
|
type: "Skill",
|
||||||
|
description: "iOS native programming languages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Xcode",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Apple's integrated development environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iOS SDK",
|
||||||
|
type: "Skill",
|
||||||
|
description: "iOS Software Development Kit and frameworks"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Frontend Developer
|
||||||
|
const uiImplementationResponsibility = Responsibility.create({
|
||||||
|
title: "User Interface Implementation",
|
||||||
|
outcome: "Pixel-perfect, responsive user interfaces that match design specifications",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "CSS Frameworks",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Bootstrap, Tailwind CSS, or similar frameworks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Design Systems",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Implementing and maintaining design system components"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const frontendTestingResponsibility = Responsibility.create({
|
||||||
|
title: "Frontend Testing",
|
||||||
|
outcome: "Comprehensive test coverage for user interface components",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Jest/Cypress",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Frontend testing frameworks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test-Driven Development",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Writing tests before implementation"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Full Stack Developer
|
||||||
|
const apiDevelopmentResponsibility = Responsibility.create({
|
||||||
|
title: "API Development",
|
||||||
|
outcome: "Robust, scalable APIs that serve frontend applications",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "RESTful Services",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Designing and implementing REST APIs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "API Documentation",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Creating comprehensive API documentation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Postman/Insomnia",
|
||||||
|
type: "Tool",
|
||||||
|
description: "API testing and documentation tools"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const systemArchitectureResponsibility = Responsibility.create({
|
||||||
|
title: "System Architecture",
|
||||||
|
outcome: "Scalable, maintainable system architecture decisions",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Microservices",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Designing microservice architectures"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Load Balancing",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Implementing load balancing strategies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Docker/Kubernetes",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Containerization and orchestration tools"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Data Analyst
|
||||||
|
const dataExplorationResponsibility = Responsibility.create({
|
||||||
|
title: "Data Exploration",
|
||||||
|
outcome: "Comprehensive understanding of data patterns and anomalies",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Exploratory Data Analysis",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Systematic approach to exploring datasets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Data Cleaning",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Identifying and correcting data quality issues"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for Machine Learning Engineer
|
||||||
|
const modelDevelopmentResponsibility = Responsibility.create({
|
||||||
|
title: "Model Development",
|
||||||
|
outcome: "Accurate, efficient machine learning models for production use",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "Feature Engineering",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Creating and selecting relevant features for ML models"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Model Validation",
|
||||||
|
type: "Skill",
|
||||||
|
description: "Cross-validation and performance evaluation techniques"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MLflow/Kubeflow",
|
||||||
|
type: "Tool",
|
||||||
|
description: "ML pipeline and experiment tracking tools"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create responsibilities for iOS Developer
|
||||||
|
const iosAppDevelopmentResponsibility = Responsibility.create({
|
||||||
|
title: "iOS App Development",
|
||||||
|
outcome: "High-quality iOS applications that meet App Store standards",
|
||||||
|
requiredAttributes: [
|
||||||
|
{
|
||||||
|
name: "UIKit/SwiftUI",
|
||||||
|
type: "Skill",
|
||||||
|
description: "iOS user interface frameworks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Core Data",
|
||||||
|
type: "Skill",
|
||||||
|
description: "iOS data persistence framework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "App Store Connect",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Apple's app distribution platform"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assemble the hierarchy
|
||||||
|
frontendDeveloper.responsibilities.push(uiImplementationResponsibility, frontendTestingResponsibility);
|
||||||
|
fullStackDeveloper.responsibilities.push(apiDevelopmentResponsibility, systemArchitectureResponsibility);
|
||||||
|
dataAnalyst.responsibilities.push(dataExplorationResponsibility);
|
||||||
|
machineLearningEngineer.responsibilities.push(modelDevelopmentResponsibility);
|
||||||
|
iosDeveloper.responsibilities.push(iosAppDevelopmentResponsibility);
|
||||||
|
|
||||||
|
webDevelopment.roles.push(frontendDeveloper, fullStackDeveloper);
|
||||||
|
dataScience.roles.push(dataAnalyst, machineLearningEngineer);
|
||||||
|
mobileDevelopment.roles.push(iosDeveloper);
|
||||||
|
|
||||||
|
technologyDomain.specializations.push(webDevelopment, dataScience, mobileDevelopment);
|
||||||
|
professionModel.domains.push(technologyDomain);
|
||||||
|
|
||||||
|
// Demonstrate the hierarchy
|
||||||
|
console.log("💻 Technology Domain Structure:");
|
||||||
|
console.log(`Domain: ${technologyDomain.name}`);
|
||||||
|
console.log(`Description: ${technologyDomain.description}`);
|
||||||
|
console.log(`Core Attributes: ${technologyDomain.coreAttributes.length}`);
|
||||||
|
|
||||||
|
technologyDomain.coreAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\nSpecializations: ${technologyDomain.specializations.length}`);
|
||||||
|
|
||||||
|
technologyDomain.specializations.forEach(spec => {
|
||||||
|
console.log(`\n🔧 ${spec.name}`);
|
||||||
|
console.log(` Focus: ${spec.focus}`);
|
||||||
|
console.log(` Core Attributes: ${spec.coreAttributes.length}`);
|
||||||
|
|
||||||
|
spec.coreAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(` Roles: ${spec.roles.length}`);
|
||||||
|
|
||||||
|
spec.roles.forEach(role => {
|
||||||
|
console.log(`\n 👨💻 ${role.title} (${role.seniority} Level)`);
|
||||||
|
console.log(` Required Attributes: ${role.requiredAttributes.length}`);
|
||||||
|
|
||||||
|
role.requiredAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(` Responsibilities: ${role.responsibilities.length}`);
|
||||||
|
|
||||||
|
role.responsibilities.forEach(resp => {
|
||||||
|
console.log(`\n 📋 ${resp.title}`);
|
||||||
|
console.log(` Outcome: ${resp.outcome}`);
|
||||||
|
console.log(` Required Attributes: ${resp.requiredAttributes.length}`);
|
||||||
|
|
||||||
|
resp.requiredAttributes.forEach(attr => {
|
||||||
|
console.log(` - ${attr.name} (${attr.type}): ${attr.description}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Demonstrate advanced querying capabilities
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("🔍 ADVANCED QUERYING EXAMPLES");
|
||||||
|
console.log("=".repeat(60));
|
||||||
|
|
||||||
|
// Find all programming languages/frameworks (skills containing common tech terms)
|
||||||
|
const programmingSkills = technologyDomain.specializations
|
||||||
|
.flatMap(spec => [
|
||||||
|
...spec.coreAttributes.filter(attr => attr.type === "Skill"),
|
||||||
|
...spec.roles.flatMap(role => [
|
||||||
|
...role.requiredAttributes.filter(attr => attr.type === "Skill"),
|
||||||
|
...role.responsibilities.flatMap(resp =>
|
||||||
|
resp.requiredAttributes.filter(attr => attr.type === "Skill")
|
||||||
|
)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
.filter(skill =>
|
||||||
|
skill.name.includes("/") ||
|
||||||
|
skill.name.includes("JavaScript") ||
|
||||||
|
skill.name.includes("Python") ||
|
||||||
|
skill.name.includes("Swift") ||
|
||||||
|
skill.name.includes("SQL")
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`\n🚀 Programming Languages & Frameworks (${programmingSkills.length}):`);
|
||||||
|
programmingSkills.forEach(skill => {
|
||||||
|
console.log(` - ${skill.name}: ${skill.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find all development tools
|
||||||
|
const developmentTools = technologyDomain.specializations
|
||||||
|
.flatMap(spec => [
|
||||||
|
...spec.coreAttributes.filter(attr => attr.type === "Tool"),
|
||||||
|
...spec.roles.flatMap(role => [
|
||||||
|
...role.requiredAttributes.filter(attr => attr.type === "Tool"),
|
||||||
|
...role.responsibilities.flatMap(resp =>
|
||||||
|
resp.requiredAttributes.filter(attr => attr.type === "Tool")
|
||||||
|
)
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log(`\n🛠️ Development Tools (${developmentTools.length}):`);
|
||||||
|
developmentTools.forEach(tool => {
|
||||||
|
console.log(` - ${tool.name}: ${tool.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find roles by seniority level
|
||||||
|
const seniorityLevels = ["Junior", "Mid", "Senior"];
|
||||||
|
seniorityLevels.forEach(level => {
|
||||||
|
const rolesAtLevel = technologyDomain.specializations
|
||||||
|
.flatMap(spec => spec.roles)
|
||||||
|
.filter(role => role.seniority === level);
|
||||||
|
|
||||||
|
if (rolesAtLevel.length > 0) {
|
||||||
|
console.log(`\n🎯 ${level} Level Roles (${rolesAtLevel.length}):`);
|
||||||
|
rolesAtLevel.forEach(role => {
|
||||||
|
console.log(` - ${role.title}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find specializations with the most roles
|
||||||
|
const specializationsByRoleCount = technologyDomain.specializations
|
||||||
|
.map(spec => ({ name: spec.name, roleCount: spec.roles.length }))
|
||||||
|
.sort((a, b) => b.roleCount - a.roleCount);
|
||||||
|
|
||||||
|
console.log(`\n📊 Specializations by Role Count:`);
|
||||||
|
specializationsByRoleCount.forEach(spec => {
|
||||||
|
console.log(` - ${spec.name}: ${spec.roleCount} roles`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate total responsibilities across the domain
|
||||||
|
const totalResponsibilities = technologyDomain.specializations
|
||||||
|
.flatMap(spec => spec.roles)
|
||||||
|
.reduce((total, role) => total + role.responsibilities.length, 0);
|
||||||
|
|
||||||
|
console.log(`\n📈 Domain Statistics:`);
|
||||||
|
console.log(` - Total Specializations: ${technologyDomain.specializations.length}`);
|
||||||
|
console.log(` - Total Roles: ${technologyDomain.specializations.flatMap(spec => spec.roles).length}`);
|
||||||
|
console.log(` - Total Responsibilities: ${totalResponsibilities}`);
|
||||||
|
console.log(` - Total Attributes: ${technologyDomain.coreAttributes.length +
|
||||||
|
technologyDomain.specializations.reduce((total, spec) =>
|
||||||
|
total + spec.coreAttributes.length +
|
||||||
|
spec.roles.reduce((roleTotal, role) =>
|
||||||
|
roleTotal + role.requiredAttributes.length +
|
||||||
|
role.responsibilities.reduce((respTotal, resp) =>
|
||||||
|
respTotal + resp.requiredAttributes.length, 0), 0), 0)}`);
|
||||||
|
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("✅ Technology example completed successfully!");
|
||||||
|
console.log("=".repeat(60));
|
521
examples/v2/software-company-example.ts
Normal file
521
examples/v2/software-company-example.ts
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
import {
|
||||||
|
Enterprise,
|
||||||
|
DomainModel,
|
||||||
|
IndustryModel,
|
||||||
|
ProfessionModel,
|
||||||
|
FieldModel,
|
||||||
|
RoleModel,
|
||||||
|
TaskModel
|
||||||
|
} from "../../lib/v2";
|
||||||
|
|
||||||
|
console.log("=== Software Company Professional Hierarchy Example (V2) ===\n");
|
||||||
|
|
||||||
|
const enterprise = Enterprise.create({});
|
||||||
|
|
||||||
|
enterprise.addDomain({
|
||||||
|
name: "STEM",
|
||||||
|
description: "Science, Technology, Engineering, and Mathematics domain"
|
||||||
|
});
|
||||||
|
|
||||||
|
const stemDomain = enterprise.domains[0];
|
||||||
|
|
||||||
|
stemDomain.addIndustry({
|
||||||
|
name: "Software",
|
||||||
|
description: "Software development and technology services industry"
|
||||||
|
});
|
||||||
|
|
||||||
|
const softwareIndustry = stemDomain.industries[0];
|
||||||
|
|
||||||
|
softwareIndustry.addProfession({
|
||||||
|
name: "Software Engineering",
|
||||||
|
description: "Design, development, and maintenance of software systems"
|
||||||
|
});
|
||||||
|
|
||||||
|
const softwareEngineering = softwareIndustry.professions[0];
|
||||||
|
|
||||||
|
const fieldData = [
|
||||||
|
{
|
||||||
|
name: "Backend Development",
|
||||||
|
description: "Server-side application development, APIs, and database management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Frontend Development",
|
||||||
|
description: "User interface and user experience development"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DevOps Engineering",
|
||||||
|
description: "Development operations, CI/CD, and infrastructure management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mobile Development",
|
||||||
|
description: "Native and cross-platform mobile application development"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Data Engineering",
|
||||||
|
description: "Data pipeline development and big data processing"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
fieldData.forEach(field => {
|
||||||
|
softwareEngineering.addField(field);
|
||||||
|
});
|
||||||
|
|
||||||
|
const [backendField, frontendField, devopsField, mobileField, dataField] = softwareEngineering.fields;
|
||||||
|
|
||||||
|
const backendRoles = [
|
||||||
|
{
|
||||||
|
title: "Senior Backend Engineer",
|
||||||
|
summary: "Lead backend development initiatives and mentor junior developers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "API Developer",
|
||||||
|
summary: "Design and implement RESTful and GraphQL APIs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Database Engineer",
|
||||||
|
summary: "Design, optimize, and maintain database systems"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
backendRoles.forEach(role => {
|
||||||
|
backendField.addRole(role);
|
||||||
|
});
|
||||||
|
|
||||||
|
const frontendRoles = [
|
||||||
|
{
|
||||||
|
title: "React Developer",
|
||||||
|
summary: "Build modern web applications using React ecosystem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "UI/UX Engineer",
|
||||||
|
summary: "Bridge design and development with focus on user experience"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
frontendRoles.forEach(role => {
|
||||||
|
frontendField.addRole(role);
|
||||||
|
});
|
||||||
|
|
||||||
|
devopsField.addRole({
|
||||||
|
title: "DevOps Engineer",
|
||||||
|
summary: "Manage CI/CD pipelines and cloud infrastructure"
|
||||||
|
});
|
||||||
|
|
||||||
|
devopsField.addRole({
|
||||||
|
title: "Site Reliability Engineer",
|
||||||
|
summary: "Ensure system reliability, monitoring, and incident response"
|
||||||
|
});
|
||||||
|
|
||||||
|
mobileField.addRole({
|
||||||
|
title: "iOS Developer",
|
||||||
|
summary: "Develop native iOS applications using Swift and iOS SDK"
|
||||||
|
});
|
||||||
|
|
||||||
|
mobileField.addRole({
|
||||||
|
title: "React Native Developer",
|
||||||
|
summary: "Build cross-platform mobile apps using React Native"
|
||||||
|
});
|
||||||
|
|
||||||
|
dataField.addRole({
|
||||||
|
title: "Data Pipeline Engineer",
|
||||||
|
summary: "Build and maintain data processing pipelines"
|
||||||
|
});
|
||||||
|
|
||||||
|
const seniorBackendEngineer = backendField.roles[0];
|
||||||
|
const apiDeveloper = backendField.roles[1];
|
||||||
|
const databaseEngineer = backendField.roles[2];
|
||||||
|
|
||||||
|
const seniorBackendTasks = [
|
||||||
|
{
|
||||||
|
name: "Design system architecture",
|
||||||
|
description: "Create scalable and maintainable system architecture designs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Code review and mentoring",
|
||||||
|
description: "Review code submissions and mentor junior team members"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Performance optimization",
|
||||||
|
description: "Identify and resolve performance bottlenecks in backend systems"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Technical documentation",
|
||||||
|
description: "Create and maintain comprehensive technical documentation"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
seniorBackendTasks.forEach(task => {
|
||||||
|
seniorBackendEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const apiDeveloperTasks = [
|
||||||
|
{
|
||||||
|
name: "Design REST endpoints",
|
||||||
|
description: "Create RESTful API endpoints following best practices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Implement GraphQL resolvers",
|
||||||
|
description: "Build GraphQL schema and resolver functions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "API documentation",
|
||||||
|
description: "Document API endpoints using OpenAPI/Swagger specifications"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "API testing",
|
||||||
|
description: "Write comprehensive tests for API endpoints"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
apiDeveloperTasks.forEach(task => {
|
||||||
|
apiDeveloper.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const databaseEngineerTasks = [
|
||||||
|
{
|
||||||
|
name: "Database schema design",
|
||||||
|
description: "Design efficient and normalized database schemas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query optimization",
|
||||||
|
description: "Optimize database queries for better performance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Database migration scripts",
|
||||||
|
description: "Create and manage database migration scripts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Backup and recovery procedures",
|
||||||
|
description: "Implement and maintain database backup and recovery strategies"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
databaseEngineerTasks.forEach(task => {
|
||||||
|
databaseEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const reactDeveloper = frontendField.roles[0];
|
||||||
|
const uiuxEngineer = frontendField.roles[1];
|
||||||
|
|
||||||
|
const reactDeveloperTasks = [
|
||||||
|
{
|
||||||
|
name: "Build React components",
|
||||||
|
description: "Create reusable and performant React components"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "State management implementation",
|
||||||
|
description: "Implement state management using Redux, Zustand, or Context API"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Frontend testing",
|
||||||
|
description: "Write unit and integration tests for React components"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bundle optimization",
|
||||||
|
description: "Optimize webpack bundles for better performance"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
reactDeveloperTasks.forEach(task => {
|
||||||
|
reactDeveloper.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const uiuxEngineerTasks = [
|
||||||
|
{
|
||||||
|
name: "Design system implementation",
|
||||||
|
description: "Implement and maintain design system components"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Accessibility compliance",
|
||||||
|
description: "Ensure applications meet WCAG accessibility standards"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "User experience optimization",
|
||||||
|
description: "Analyze and improve user interaction patterns"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
uiuxEngineerTasks.forEach(task => {
|
||||||
|
uiuxEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const devopsEngineer = devopsField.roles[0];
|
||||||
|
const sreEngineer = devopsField.roles[1];
|
||||||
|
|
||||||
|
const devopsEngineerTasks = [
|
||||||
|
{
|
||||||
|
name: "CI/CD pipeline setup",
|
||||||
|
description: "Configure continuous integration and deployment pipelines"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Infrastructure as Code",
|
||||||
|
description: "Manage infrastructure using Terraform, CloudFormation, or similar tools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Container orchestration",
|
||||||
|
description: "Deploy and manage applications using Docker and Kubernetes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cloud resource management",
|
||||||
|
description: "Optimize cloud resource usage and costs"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
devopsEngineerTasks.forEach(task => {
|
||||||
|
devopsEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const sreEngineerTasks = [
|
||||||
|
{
|
||||||
|
name: "Monitoring and alerting",
|
||||||
|
description: "Set up comprehensive monitoring and alerting systems"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Incident response",
|
||||||
|
description: "Respond to and resolve production incidents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Capacity planning",
|
||||||
|
description: "Plan and manage system capacity and scaling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Post-mortem analysis",
|
||||||
|
description: "Conduct post-incident analysis and implement improvements"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
sreEngineerTasks.forEach(task => {
|
||||||
|
sreEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const iosDeveloper = mobileField.roles[0];
|
||||||
|
const reactNativeDeveloper = mobileField.roles[1];
|
||||||
|
|
||||||
|
const iosDeveloperTasks = [
|
||||||
|
{
|
||||||
|
name: "iOS app development",
|
||||||
|
description: "Build native iOS applications using Swift and UIKit/SwiftUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "App Store submission",
|
||||||
|
description: "Prepare and submit apps to the Apple App Store"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iOS performance optimization",
|
||||||
|
description: "Optimize app performance and memory usage"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
iosDeveloperTasks.forEach(task => {
|
||||||
|
iosDeveloper.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const reactNativeDeveloperTasks = [
|
||||||
|
{
|
||||||
|
name: "Cross-platform development",
|
||||||
|
description: "Build apps that work on both iOS and Android platforms"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Native module integration",
|
||||||
|
description: "Integrate native iOS and Android modules when needed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "App performance tuning",
|
||||||
|
description: "Optimize React Native app performance and bundle size"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
reactNativeDeveloperTasks.forEach(task => {
|
||||||
|
reactNativeDeveloper.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataPipelineEngineer = dataField.roles[0];
|
||||||
|
|
||||||
|
const dataPipelineEngineerTasks = [
|
||||||
|
{
|
||||||
|
name: "ETL pipeline development",
|
||||||
|
description: "Build Extract, Transform, Load pipelines for data processing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Data quality monitoring",
|
||||||
|
description: "Implement data quality checks and monitoring systems"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Big data processing",
|
||||||
|
description: "Process large datasets using Spark, Hadoop, or similar technologies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Data warehouse management",
|
||||||
|
description: "Design and maintain data warehouse schemas and processes"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
dataPipelineEngineerTasks.forEach(task => {
|
||||||
|
dataPipelineEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("🏢 Software Company Hierarchy Structure:");
|
||||||
|
console.log("=".repeat(60));
|
||||||
|
|
||||||
|
console.log(`\n🌐 Domain: ${stemDomain.name}`);
|
||||||
|
console.log(` Description: ${stemDomain.description}`);
|
||||||
|
console.log(` Industries: ${stemDomain.industries.length}`);
|
||||||
|
|
||||||
|
stemDomain.industries.forEach(industry => {
|
||||||
|
console.log(`\n 🏭 Industry: ${industry.name}`);
|
||||||
|
console.log(` Description: ${industry.description}`);
|
||||||
|
console.log(` Professions: ${industry.professions.length}`);
|
||||||
|
|
||||||
|
industry.professions.forEach(profession => {
|
||||||
|
console.log(`\n 👨💼 Profession: ${profession.name}`);
|
||||||
|
console.log(` Description: ${profession.description}`);
|
||||||
|
console.log(` Fields: ${profession.fields.length}`);
|
||||||
|
|
||||||
|
profession.fields.forEach(field => {
|
||||||
|
console.log(`\n 🔧 Field: ${field.name}`);
|
||||||
|
console.log(` Description: ${field.description}`);
|
||||||
|
console.log(` Roles: ${field.roles.length}`);
|
||||||
|
|
||||||
|
field.roles.forEach(role => {
|
||||||
|
console.log(`\n 👤 Role: ${role.title}`);
|
||||||
|
console.log(` Summary: ${role.summary}`);
|
||||||
|
console.log(` Tasks: ${role.tasks.length}`);
|
||||||
|
|
||||||
|
role.tasks.forEach((task, index) => {
|
||||||
|
console.log(` ${index + 1}. ${task.name}`);
|
||||||
|
if (task.description) {
|
||||||
|
console.log(` → ${task.description}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("🔍 V2 ADVANCED FEATURES DEMONSTRATION");
|
||||||
|
console.log("=".repeat(60));
|
||||||
|
|
||||||
|
console.log("\n🆔 UUID Identifiers:");
|
||||||
|
console.log(`Domain ID: ${stemDomain.id}`);
|
||||||
|
console.log(`Industry ID: ${softwareIndustry.id}`);
|
||||||
|
console.log(`Profession ID: ${softwareEngineering.id}`);
|
||||||
|
console.log(`First Field ID: ${backendField.id}`);
|
||||||
|
console.log(`First Role ID: ${seniorBackendEngineer.id}`);
|
||||||
|
console.log(`First Task ID: ${seniorBackendEngineer.tasks[0].id}`);
|
||||||
|
|
||||||
|
console.log(`\n📊 All Tasks in Software Industry (${softwareIndustry.allTasks.length}):`);
|
||||||
|
softwareIndustry.allTasks.forEach((task, index) => {
|
||||||
|
console.log(`${index + 1}. ${task.name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n🔧 Tasks by Field:`);
|
||||||
|
softwareEngineering.fields.forEach(field => {
|
||||||
|
console.log(`${field.name}: ${field.allTasks.length} tasks`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\n⚡ CRUD Operations Demonstration:");
|
||||||
|
|
||||||
|
console.log("\n➕ Adding new field: 'Quality Assurance'");
|
||||||
|
softwareEngineering.addField({
|
||||||
|
name: "Quality Assurance",
|
||||||
|
description: "Software testing and quality assurance"
|
||||||
|
});
|
||||||
|
|
||||||
|
const qaField = softwareEngineering.fields[softwareEngineering.fields.length - 1];
|
||||||
|
console.log(`✅ Added field: ${qaField.name} (ID: ${qaField.id})`);
|
||||||
|
|
||||||
|
qaField.addRole({
|
||||||
|
title: "QA Engineer",
|
||||||
|
summary: "Ensure software quality through comprehensive testing"
|
||||||
|
});
|
||||||
|
|
||||||
|
const qaEngineer = qaField.roles[0];
|
||||||
|
console.log(`✅ Added role: ${qaEngineer.title} (ID: ${qaEngineer.id})`);
|
||||||
|
|
||||||
|
const qaTasks = [
|
||||||
|
{
|
||||||
|
name: "Test case development",
|
||||||
|
description: "Create comprehensive test cases for software features"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Automated testing",
|
||||||
|
description: "Develop and maintain automated test suites"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bug reporting and tracking",
|
||||||
|
description: "Identify, document, and track software defects"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
qaTasks.forEach(task => {
|
||||||
|
qaEngineer.addTask(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✅ Added ${qaTasks.length} tasks to QA Engineer`);
|
||||||
|
|
||||||
|
const firstQATask = qaEngineer.tasks[0];
|
||||||
|
console.log(`\n✏️ Updating task: "${firstQATask.name}"`);
|
||||||
|
firstQATask.update({
|
||||||
|
name: "Comprehensive Test Case Development",
|
||||||
|
description: "Create detailed test cases covering functional, integration, and edge cases"
|
||||||
|
});
|
||||||
|
console.log(`✅ Updated to: "${firstQATask.name}"`);
|
||||||
|
|
||||||
|
console.log(`\n🗑️ Removing last task from QA Engineer`);
|
||||||
|
const taskToRemove = qaEngineer.tasks[qaEngineer.tasks.length - 1];
|
||||||
|
console.log(`Removing: "${taskToRemove.name}"`);
|
||||||
|
qaEngineer.removeTask(taskToRemove);
|
||||||
|
console.log(`✅ Task removed. QA Engineer now has ${qaEngineer.tasks.length} tasks`);
|
||||||
|
|
||||||
|
console.log("\n🔍 Advanced Querying:");
|
||||||
|
|
||||||
|
const engineerRoles = softwareEngineering.fields
|
||||||
|
.flatMap(field => field.roles)
|
||||||
|
.filter(role => role.title.includes("Engineer"));
|
||||||
|
|
||||||
|
console.log(`\n👷 Roles with "Engineer" in title (${engineerRoles.length}):`);
|
||||||
|
engineerRoles.forEach(role => {
|
||||||
|
console.log(` - ${role.title}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fieldTaskCounts = softwareEngineering.fields
|
||||||
|
.map(field => ({
|
||||||
|
name: field.name,
|
||||||
|
taskCount: field.allTasks.length
|
||||||
|
}))
|
||||||
|
.sort((a, b) => b.taskCount - a.taskCount);
|
||||||
|
|
||||||
|
console.log(`\n📈 Fields by Task Count:`);
|
||||||
|
fieldTaskCounts.forEach(field => {
|
||||||
|
console.log(` - ${field.name}: ${field.taskCount} tasks`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const developmentTasks = enterprise.allTasks
|
||||||
|
.filter(task =>
|
||||||
|
task.name.toLowerCase().includes("develop") ||
|
||||||
|
task.description?.toLowerCase().includes("develop")
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`\n💻 Development-related Tasks (${developmentTasks.length}):`);
|
||||||
|
developmentTasks.forEach(task => {
|
||||||
|
console.log(` - ${task.name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\n📊 Complete Hierarchy Statistics:");
|
||||||
|
console.log(` - Domains: ${enterprise.domains.length}`);
|
||||||
|
console.log(` - Industries: ${enterprise.domains.reduce((sum, d) => sum + d.industries.length, 0)}`);
|
||||||
|
console.log(` - Professions: ${enterprise.domains.reduce((sum, d) => sum + d.industries.reduce((sum2, i) => sum2 + i.professions.length, 0), 0)}`);
|
||||||
|
console.log(` - Fields: ${enterprise.domains.reduce((sum, d) => sum + d.industries.reduce((sum2, i) => sum2 + i.professions.reduce((sum3, p) => sum3 + p.fields.length, 0), 0), 0)}`);
|
||||||
|
console.log(` - Roles: ${enterprise.domains.reduce((sum, d) => sum + d.industries.reduce((sum2, i) => sum2 + i.professions.reduce((sum3, p) => sum3 + p.fields.reduce((sum4, f) => sum4 + f.roles.length, 0), 0), 0), 0)}`);
|
||||||
|
console.log(` - Tasks: ${enterprise.allTasks.length}`);
|
||||||
|
|
||||||
|
console.log("\n" + "=".repeat(60));
|
||||||
|
console.log("✅ Software Company example completed successfully!");
|
||||||
|
console.log("This example demonstrates the full 6-layer hierarchy with:");
|
||||||
|
console.log(" • UUID-based identifiers for distributed systems");
|
||||||
|
console.log(" • Comprehensive CRUD operations");
|
||||||
|
console.log(" • Compositional queries and views");
|
||||||
|
console.log(" • Real-world software company structure");
|
||||||
|
console.log(" • Advanced querying capabilities");
|
||||||
|
console.log("=".repeat(60));
|
125
generate-template.ts
Executable file
125
generate-template.ts
Executable file
@@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hierarchyGenerator.ts
|
||||||
|
* ------------------------------------------------------------
|
||||||
|
* A tiny OpenAI‑powered helper that turns natural‑language prompts
|
||||||
|
* into domain hierarchies matching `HierarchyModel` (mobx‑state‑tree).
|
||||||
|
* ------------------------------------------------------------
|
||||||
|
* Usage example:
|
||||||
|
* import { generateHierarchy } from "./hierarchyGenerator";
|
||||||
|
* const hierarchy = await generateHierarchy("Create a v2 Healthcare hierarchy for mental health services");
|
||||||
|
*
|
||||||
|
* The function returns a live MST instance of `HierarchyModel` so it
|
||||||
|
* can be plugged straight into your state tree or persisted as JSON.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import OpenAI from "openai";
|
||||||
|
import { HierarchyModel } from "./lib/hierarchy-model.ts";
|
||||||
|
import type { Instance } from "mobx-state-tree";
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Type Definitions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shape produced by the LLM and accepted by `HierarchyModel`.
|
||||||
|
*/
|
||||||
|
export interface Hierarchy {
|
||||||
|
version: "v1" | "v2";
|
||||||
|
domain: string; // e.g. "Finance", "Technology"
|
||||||
|
structure: string[]; // ordered list of hierarchy labels
|
||||||
|
description: string; // plain‑text description
|
||||||
|
commonSkills: string[];
|
||||||
|
commonTools: string[];
|
||||||
|
examples: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// OpenAI client configuration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const openai = new OpenAI({
|
||||||
|
// Rely on OPENAI_API_KEY env var or pass explicit key here
|
||||||
|
apiKey: process.env.OPENAI_API_KEY,
|
||||||
|
});
|
||||||
|
|
||||||
|
// System prompt used for every request. Keeps the model focused on
|
||||||
|
// emitting strict JSON with NO extra text.
|
||||||
|
const SYS_PROMPT = `
|
||||||
|
You are an API that converts natural‑language descriptions into JSON
|
||||||
|
objects that conform **exactly** to the following TypeScript interface.
|
||||||
|
Return the JSON only – no markdown, comments, or additional keys.
|
||||||
|
If a field is missing in the user's request, make a sensible inference.
|
||||||
|
|
||||||
|
interface Hierarchy {
|
||||||
|
version: "v1" | "v2"; // one of the two schema versions
|
||||||
|
domain: string; // high‑level sector name
|
||||||
|
structure: string[]; // ordered labels, 4 elements for v1, 6 for v2
|
||||||
|
description: string; // concise explanation of the hierarchy
|
||||||
|
commonSkills: string[]; // 3‑7 bullet items
|
||||||
|
commonTools: string[]; // 3‑7 bullet items
|
||||||
|
examples: string[]; // 3‑7 representative examples
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Public API
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a natural‑language prompt into a fully‑typed `HierarchyModel`.
|
||||||
|
*
|
||||||
|
* @param nlPrompt – Human description, e.g. "Define a v1 hierarchy for legal services"
|
||||||
|
* @param model – (optional) Which OpenAI model to use. Defaults to GPT‑4o‑mini.
|
||||||
|
*/
|
||||||
|
export async function generateHierarchy(
|
||||||
|
nlPrompt: string,
|
||||||
|
model: string = "gpt-4o-mini"
|
||||||
|
): Promise<Instance<typeof HierarchyModel>> {
|
||||||
|
const chat = await openai.chat.completions.create({
|
||||||
|
model,
|
||||||
|
response_format: { type: "json_object" }, // guarantees pure JSON
|
||||||
|
messages: [
|
||||||
|
{ role: "system", content: SYS_PROMPT },
|
||||||
|
{ role: "user", content: nlPrompt },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Defensive parsing — in rare cases the assistant may wrap JSON in text.
|
||||||
|
const raw = chat.choices[0]?.message?.content ?? "{}";
|
||||||
|
let data: Hierarchy;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(raw) as Hierarchy;
|
||||||
|
} catch {
|
||||||
|
// Attempt to salvage JSON embedded in text
|
||||||
|
const match = raw.match(/\{[\s\S]*\}/);
|
||||||
|
if (!match) throw new Error("Failed to parse JSON from LLM response");
|
||||||
|
data = JSON.parse(match[0]) as Hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate minimal shape before creating MST instance.
|
||||||
|
if (!data.version || !data.domain || !data.structure) {
|
||||||
|
throw new Error("Incomplete hierarchy returned by LLM");
|
||||||
|
}
|
||||||
|
|
||||||
|
return HierarchyModel.create(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Helper: quick command‑line demo when run with ts‑node
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
(async () => {
|
||||||
|
const prompt = process.argv.slice(2).join(" ") ||
|
||||||
|
"Create a v2 Technology hierarchy focused on AI safety";
|
||||||
|
try {
|
||||||
|
const hierarchy = await generateHierarchy(prompt);
|
||||||
|
console.log(JSON.stringify(hierarchy.toJSON(), null, 2));
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error generating hierarchy:", err);
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
199
index.ts
Normal file
199
index.ts
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import HierarchyAgent from './lib/agent-wrapper';
|
||||||
|
import { writeFileSync, mkdirSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
// Create the hierarchy agent with enhanced instructions
|
||||||
|
const hierarchyAgent = new HierarchyAgent({
|
||||||
|
name: 'Professional Hierarchy Generator',
|
||||||
|
instructions: `You are an expert at creating professional hierarchy models.
|
||||||
|
You understand organizational structures, job roles, skills, and professional development paths.
|
||||||
|
Generate comprehensive, realistic examples that demonstrate best practices in professional modeling.
|
||||||
|
|
||||||
|
Focus on creating practical, implementable hierarchies that reflect real-world organizational structures.
|
||||||
|
Include relevant skills, tools, and technologies for each role.
|
||||||
|
Provide clear examples of how the hierarchy can be used in practice.`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Demonstrate the modular agent capabilities
|
||||||
|
async function demonstrateAgentCapabilities() {
|
||||||
|
console.log('🚀 Demonstrating Professional Hierarchy Agent Capabilities...\n');
|
||||||
|
|
||||||
|
// Show available templates
|
||||||
|
console.log('📋 Available Templates:');
|
||||||
|
const templates = hierarchyAgent.getAvailableTemplates();
|
||||||
|
templates.forEach(template => {
|
||||||
|
console.log(` - ${template.domain} (${template.version}): ${template.description}`);
|
||||||
|
});
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
// Generate examples using different approaches
|
||||||
|
const examples = [
|
||||||
|
{
|
||||||
|
name: 'Education Domain (using template)',
|
||||||
|
options: {
|
||||||
|
domain: 'education',
|
||||||
|
templateKey: 'education-v2',
|
||||||
|
complexity: 'complex' as const,
|
||||||
|
includeSkills: true,
|
||||||
|
includeTools: true,
|
||||||
|
includeExamples: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Manufacturing Domain (custom generation)',
|
||||||
|
options: {
|
||||||
|
domain: 'manufacturing',
|
||||||
|
version: 'v2' as const,
|
||||||
|
complexity: 'medium' as const,
|
||||||
|
includeSkills: true,
|
||||||
|
includeTools: true,
|
||||||
|
includeExamples: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Retail Domain (simple v1)',
|
||||||
|
options: {
|
||||||
|
domain: 'retail',
|
||||||
|
version: 'v1' as const,
|
||||||
|
complexity: 'simple' as const,
|
||||||
|
includeSkills: false,
|
||||||
|
includeTools: false,
|
||||||
|
includeExamples: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Create examples directory
|
||||||
|
const examplesDir = join(process.cwd(), 'examples', 'generated');
|
||||||
|
mkdirSync(examplesDir, { recursive: true });
|
||||||
|
|
||||||
|
// Generate each example with streaming for visibility
|
||||||
|
for (const example of examples) {
|
||||||
|
try {
|
||||||
|
console.log(`📊 Generating: ${example.name}...`);
|
||||||
|
console.log('🔍 Watch the agent work in real-time:\n');
|
||||||
|
|
||||||
|
// Use streaming to show what the agent is doing
|
||||||
|
const result = await hierarchyAgent.generateHierarchyWithStreaming(
|
||||||
|
example.options,
|
||||||
|
(event) => {
|
||||||
|
// Enhanced trace information for agent activities
|
||||||
|
if (event.type === 'agent_updated_stream_event') {
|
||||||
|
console.log(`[TRACE] 🤖 Agent: ${event.agent?.name || 'Unknown'} - Status updated`);
|
||||||
|
} else if (event.type === 'run_item_stream_event') {
|
||||||
|
if (event.item?.type === 'tool_call_item') {
|
||||||
|
console.log(`[TRACE] 🔧 Tool Call: ${event.item.tool_call?.function?.name || 'Unknown tool'}`);
|
||||||
|
if (event.item.tool_call?.function?.arguments) {
|
||||||
|
try {
|
||||||
|
const args = JSON.parse(event.item.tool_call.function.arguments);
|
||||||
|
console.log(`[TRACE] 📋 Tool Arguments: ${JSON.stringify(args, null, 2)}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`[TRACE] 📋 Tool Arguments: ${event.item.tool_call.function.arguments}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event.item?.type === 'tool_call_output_item') {
|
||||||
|
console.log(`[TRACE] ✅ Tool Output: Received response`);
|
||||||
|
} else if (event.item?.type === 'message_output_item') {
|
||||||
|
console.log(`[TRACE] 💬 Message: Generating response content`);
|
||||||
|
}
|
||||||
|
} else if (event.type === 'raw_model_stream_event' && event.delta?.content) {
|
||||||
|
// Show partial content being generated (throttled)
|
||||||
|
process.stdout.write('.');
|
||||||
|
} else if (event.type === 'run_started_stream_event') {
|
||||||
|
console.log(`[TRACE] 🚀 Run Started: Beginning agent execution`);
|
||||||
|
} else if (event.type === 'run_completed_stream_event') {
|
||||||
|
console.log(`[TRACE] 🏁 Run Completed: Agent execution finished`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(); // New line after dots
|
||||||
|
|
||||||
|
// Write the generated example to a file
|
||||||
|
const filepath = join(examplesDir, `${result.filename}.${result.extension}`);
|
||||||
|
writeFileSync(filepath, result.content);
|
||||||
|
|
||||||
|
console.log(`✅ Generated: ${filepath}`);
|
||||||
|
console.log(` Format: typescript (default)`);
|
||||||
|
console.log(` Complexity: ${example.options.complexity}`);
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error generating ${example.name}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demonstrate batch generation with streaming
|
||||||
|
console.log('🔄 Demonstrating batch generation with streaming...');
|
||||||
|
const batchDomains = ['logistics', 'consulting', 'media'];
|
||||||
|
|
||||||
|
const batchResults = [];
|
||||||
|
for (const domain of batchDomains) {
|
||||||
|
try {
|
||||||
|
console.log(`📊 Batch generating: ${domain} domain...`);
|
||||||
|
console.log('🔍 Streaming agent progress:\n');
|
||||||
|
|
||||||
|
const result = await hierarchyAgent.generateHierarchyWithStreaming({
|
||||||
|
domain,
|
||||||
|
version: 'v2',
|
||||||
|
complexity: 'medium',
|
||||||
|
includeSkills: true,
|
||||||
|
includeTools: true,
|
||||||
|
includeExamples: true
|
||||||
|
}, (event) => {
|
||||||
|
// Enhanced trace information for batch generation
|
||||||
|
if (event.type === 'agent_updated_stream_event') {
|
||||||
|
console.log(`[BATCH TRACE] 🤖 Agent: ${event.agent?.name || 'Unknown'} - Status updated`);
|
||||||
|
} else if (event.type === 'run_item_stream_event') {
|
||||||
|
if (event.item?.type === 'tool_call_item') {
|
||||||
|
console.log(`[BATCH TRACE] 🔧 Tool Call: ${event.item.tool_call?.function?.name || 'Unknown tool'}`);
|
||||||
|
if (event.item.tool_call?.function?.arguments) {
|
||||||
|
try {
|
||||||
|
const args = JSON.parse(event.item.tool_call.function.arguments);
|
||||||
|
console.log(`[BATCH TRACE] 📋 Tool Arguments: ${JSON.stringify(args, null, 2)}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`[BATCH TRACE] 📋 Tool Arguments: ${event.item.tool_call.function.arguments}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event.item?.type === 'tool_call_output_item') {
|
||||||
|
console.log(`[BATCH TRACE] ✅ Tool Output: Received response`);
|
||||||
|
} else if (event.item?.type === 'message_output_item') {
|
||||||
|
console.log(`[BATCH TRACE] 💬 Message: Generating response content`);
|
||||||
|
}
|
||||||
|
} else if (event.type === 'raw_model_stream_event' && event.delta?.content) {
|
||||||
|
// Show partial content being generated (throttled)
|
||||||
|
process.stdout.write('.');
|
||||||
|
} else if (event.type === 'run_started_stream_event') {
|
||||||
|
console.log(`[BATCH TRACE] 🚀 Run Started: Beginning agent execution for ${domain}`);
|
||||||
|
} else if (event.type === 'run_completed_stream_event') {
|
||||||
|
console.log(`[BATCH TRACE] 🏁 Run Completed: Agent execution finished for ${domain}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(); // New line after dots
|
||||||
|
batchResults.push(result);
|
||||||
|
|
||||||
|
// Save batch result immediately
|
||||||
|
const filepath = join(examplesDir, `batch-${result.filename}.${result.extension}`);
|
||||||
|
writeFileSync(filepath, result.content);
|
||||||
|
console.log(`✅ Batch generated: ${filepath}`);
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error in batch generation for ${domain}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n🎉 Agent capability demonstration complete!');
|
||||||
|
console.log(`📁 All examples saved to: ${examplesDir}`);
|
||||||
|
|
||||||
|
// Show summary
|
||||||
|
console.log('\n📊 Generation Summary:');
|
||||||
|
console.log(` Individual examples: ${examples.length}`);
|
||||||
|
console.log(` Batch examples: ${batchResults.length}`);
|
||||||
|
console.log(` Total files generated: ${examples.length + batchResults.length}`);
|
||||||
|
console.log(` Available templates: ${templates.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the demonstration
|
||||||
|
demonstrateAgentCapabilities().catch(console.error);
|
252
lib/__tests__/v1.test.ts
Normal file
252
lib/__tests__/v1.test.ts
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
import { expect, test, describe } from "bun:test";
|
||||||
|
import { ProfessionModel, Domain, Specialization, Role, Responsibility, Attribute } from "../v1.ts";
|
||||||
|
|
||||||
|
describe("V1 Professional Hierarchy Model", () => {
|
||||||
|
describe("Attribute Model", () => {
|
||||||
|
test("should create an attribute with required fields", () => {
|
||||||
|
const attribute = Attribute.create({
|
||||||
|
name: "JavaScript",
|
||||||
|
type: "Skill"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(attribute.name).toBe("JavaScript");
|
||||||
|
expect(attribute.type).toBe("Skill");
|
||||||
|
expect(attribute.description).toBe("");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create an attribute with description", () => {
|
||||||
|
const attribute = Attribute.create({
|
||||||
|
name: "React",
|
||||||
|
type: "Tool",
|
||||||
|
description: "Frontend library for building user interfaces"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(attribute.name).toBe("React");
|
||||||
|
expect(attribute.type).toBe("Tool");
|
||||||
|
expect(attribute.description).toBe("Frontend library for building user interfaces");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should accept all valid attribute types", () => {
|
||||||
|
const skill = Attribute.create({ name: "Problem Solving", type: "Skill" });
|
||||||
|
const tool = Attribute.create({ name: "VS Code", type: "Tool" });
|
||||||
|
const trait = Attribute.create({ name: "Leadership", type: "Trait" });
|
||||||
|
|
||||||
|
expect(skill.type).toBe("Skill");
|
||||||
|
expect(tool.type).toBe("Tool");
|
||||||
|
expect(trait.type).toBe("Trait");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Responsibility Model", () => {
|
||||||
|
test("should create a responsibility with required attributes", () => {
|
||||||
|
const jsAttribute = Attribute.create({ name: "JavaScript", type: "Skill" });
|
||||||
|
const reactAttribute = Attribute.create({ name: "React", type: "Tool" });
|
||||||
|
|
||||||
|
const responsibility = Responsibility.create({
|
||||||
|
title: "Build User Interfaces",
|
||||||
|
outcome: "Functional and responsive web applications",
|
||||||
|
requiredAttributes: [jsAttribute, reactAttribute]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(responsibility.title).toBe("Build User Interfaces");
|
||||||
|
expect(responsibility.outcome).toBe("Functional and responsive web applications");
|
||||||
|
expect(responsibility.requiredAttributes).toHaveLength(2);
|
||||||
|
expect(responsibility.requiredAttributes[0].name).toBe("JavaScript");
|
||||||
|
expect(responsibility.requiredAttributes[1].name).toBe("React");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create a responsibility with empty attributes array", () => {
|
||||||
|
const responsibility = Responsibility.create({
|
||||||
|
title: "Code Review",
|
||||||
|
outcome: "High quality code",
|
||||||
|
requiredAttributes: []
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(responsibility.requiredAttributes).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Role Model", () => {
|
||||||
|
test("should create a role with all seniority levels", () => {
|
||||||
|
const seniorityLevels = ["Intern", "Junior", "Mid", "Senior", "Lead", "Principal"];
|
||||||
|
|
||||||
|
seniorityLevels.forEach(level => {
|
||||||
|
const role = Role.create({
|
||||||
|
title: `${level} Developer`,
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [],
|
||||||
|
seniority: level as any
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(role.seniority).toBe(level);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create a role with responsibilities and attributes", () => {
|
||||||
|
const attributeForResponsibility = Attribute.create({ name: "TypeScript", type: "Skill" });
|
||||||
|
const attributeForRole = Attribute.create({ name: "TypeScript", type: "Skill" });
|
||||||
|
const responsibility = Responsibility.create({
|
||||||
|
title: "Develop Features",
|
||||||
|
outcome: "Working software features",
|
||||||
|
requiredAttributes: [attributeForResponsibility]
|
||||||
|
});
|
||||||
|
|
||||||
|
const role = Role.create({
|
||||||
|
title: "Frontend Developer",
|
||||||
|
responsibilities: [responsibility],
|
||||||
|
requiredAttributes: [attributeForRole],
|
||||||
|
seniority: "Mid"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(role.title).toBe("Frontend Developer");
|
||||||
|
expect(role.responsibilities).toHaveLength(1);
|
||||||
|
expect(role.requiredAttributes).toHaveLength(1);
|
||||||
|
expect(role.seniority).toBe("Mid");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Specialization Model", () => {
|
||||||
|
test("should create a specialization with roles and attributes", () => {
|
||||||
|
const coreAttribute = Attribute.create({ name: "Web Development", type: "Skill" });
|
||||||
|
const role = Role.create({
|
||||||
|
title: "Web Developer",
|
||||||
|
responsibilities: [],
|
||||||
|
requiredAttributes: [],
|
||||||
|
seniority: "Mid"
|
||||||
|
});
|
||||||
|
|
||||||
|
const specialization = Specialization.create({
|
||||||
|
name: "Frontend Development",
|
||||||
|
focus: "User interface and experience",
|
||||||
|
coreAttributes: [coreAttribute],
|
||||||
|
roles: [role]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(specialization.name).toBe("Frontend Development");
|
||||||
|
expect(specialization.focus).toBe("User interface and experience");
|
||||||
|
expect(specialization.coreAttributes).toHaveLength(1);
|
||||||
|
expect(specialization.roles).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Domain Model", () => {
|
||||||
|
test("should create a domain with specializations", () => {
|
||||||
|
const attribute = Attribute.create({ name: "Programming", type: "Skill" });
|
||||||
|
const specialization = Specialization.create({
|
||||||
|
name: "Software Engineering",
|
||||||
|
focus: "Building software systems",
|
||||||
|
coreAttributes: [],
|
||||||
|
roles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const domain = Domain.create({
|
||||||
|
name: "Technology",
|
||||||
|
description: "Technology and software development",
|
||||||
|
specializations: [specialization],
|
||||||
|
coreAttributes: [attribute]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(domain.name).toBe("Technology");
|
||||||
|
expect(domain.description).toBe("Technology and software development");
|
||||||
|
expect(domain.specializations).toHaveLength(1);
|
||||||
|
expect(domain.coreAttributes).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create a domain with empty description", () => {
|
||||||
|
const domain = Domain.create({
|
||||||
|
name: "Engineering",
|
||||||
|
specializations: [],
|
||||||
|
coreAttributes: []
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(domain.description).toBe("");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("ProfessionModel", () => {
|
||||||
|
test("should create a profession model with domains", () => {
|
||||||
|
const domain = Domain.create({
|
||||||
|
name: "Healthcare",
|
||||||
|
specializations: [],
|
||||||
|
coreAttributes: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const professionModel = ProfessionModel.create({
|
||||||
|
domains: [domain]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(professionModel.domains).toHaveLength(1);
|
||||||
|
expect(professionModel.domains[0].name).toBe("Healthcare");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create an empty profession model", () => {
|
||||||
|
const professionModel = ProfessionModel.create({
|
||||||
|
domains: []
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(professionModel.domains).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Complete Hierarchy Integration", () => {
|
||||||
|
test("should create a complete professional hierarchy", () => {
|
||||||
|
const jsSkillForResponsibility = Attribute.create({ name: "JavaScript", type: "Skill" });
|
||||||
|
const reactToolForResponsibility = Attribute.create({ name: "React", type: "Tool" });
|
||||||
|
|
||||||
|
// Create attributes for role
|
||||||
|
const jsSkillForRole = Attribute.create({ name: "JavaScript", type: "Skill" });
|
||||||
|
const reactToolForRole = Attribute.create({ name: "React", type: "Tool" });
|
||||||
|
const leadershipTrait = Attribute.create({ name: "Leadership", type: "Trait" });
|
||||||
|
|
||||||
|
const jsSkillForSpecialization = Attribute.create({ name: "JavaScript", type: "Skill" });
|
||||||
|
const reactToolForSpecialization = Attribute.create({ name: "React", type: "Tool" });
|
||||||
|
|
||||||
|
const jsSkillForDomain = Attribute.create({ name: "JavaScript", type: "Skill" });
|
||||||
|
|
||||||
|
const responsibility = Responsibility.create({
|
||||||
|
title: "Build React Applications",
|
||||||
|
outcome: "Scalable web applications",
|
||||||
|
requiredAttributes: [jsSkillForResponsibility, reactToolForResponsibility]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create role
|
||||||
|
const role = Role.create({
|
||||||
|
title: "Senior Frontend Developer",
|
||||||
|
responsibilities: [responsibility],
|
||||||
|
requiredAttributes: [jsSkillForRole, reactToolForRole, leadershipTrait],
|
||||||
|
seniority: "Senior"
|
||||||
|
});
|
||||||
|
|
||||||
|
const specialization = Specialization.create({
|
||||||
|
name: "Frontend Development",
|
||||||
|
focus: "User interfaces and client-side applications",
|
||||||
|
coreAttributes: [jsSkillForSpecialization, reactToolForSpecialization],
|
||||||
|
roles: [role]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create domain
|
||||||
|
const domain = Domain.create({
|
||||||
|
name: "Software Engineering",
|
||||||
|
description: "Building software systems and applications",
|
||||||
|
specializations: [specialization],
|
||||||
|
coreAttributes: [jsSkillForDomain]
|
||||||
|
});
|
||||||
|
|
||||||
|
const professionModel = ProfessionModel.create({
|
||||||
|
domains: [domain]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify the complete hierarchy
|
||||||
|
expect(professionModel.domains).toHaveLength(1);
|
||||||
|
expect(professionModel.domains[0].specializations).toHaveLength(1);
|
||||||
|
expect(professionModel.domains[0].specializations[0].roles).toHaveLength(1);
|
||||||
|
expect(professionModel.domains[0].specializations[0].roles[0].responsibilities).toHaveLength(1);
|
||||||
|
|
||||||
|
const retrievedRole = professionModel.domains[0].specializations[0].roles[0];
|
||||||
|
expect(retrievedRole.title).toBe("Senior Frontend Developer");
|
||||||
|
expect(retrievedRole.seniority).toBe("Senior");
|
||||||
|
expect(retrievedRole.responsibilities[0].title).toBe("Build React Applications");
|
||||||
|
expect(retrievedRole.requiredAttributes).toHaveLength(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
476
lib/__tests__/v2.test.ts
Normal file
476
lib/__tests__/v2.test.ts
Normal file
@@ -0,0 +1,476 @@
|
|||||||
|
import { expect, test, describe, beforeEach } from "bun:test";
|
||||||
|
import {
|
||||||
|
TaskModel,
|
||||||
|
RoleModel,
|
||||||
|
FieldModel,
|
||||||
|
ProfessionModel,
|
||||||
|
IndustryModel,
|
||||||
|
DomainModel,
|
||||||
|
Enterprise,
|
||||||
|
Task,
|
||||||
|
Role,
|
||||||
|
Field,
|
||||||
|
Profession,
|
||||||
|
Industry,
|
||||||
|
Domain,
|
||||||
|
IRootStore
|
||||||
|
} from "../v2.ts";
|
||||||
|
|
||||||
|
describe("V2 Professional Hierarchy Model", () => {
|
||||||
|
describe("TaskModel", () => {
|
||||||
|
test("should create a task with UUID identifier", () => {
|
||||||
|
const task = TaskModel.create({
|
||||||
|
name: "Design REST endpoints"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(task.name).toBe("Design REST endpoints");
|
||||||
|
expect(task.id).toBeDefined();
|
||||||
|
expect(typeof task.id).toBe("string");
|
||||||
|
expect(task.id.length).toBeGreaterThan(0);
|
||||||
|
expect(task.description).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create a task with description", () => {
|
||||||
|
const task = TaskModel.create({
|
||||||
|
name: "Write unit tests",
|
||||||
|
description: "Create comprehensive test coverage for new features"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(task.name).toBe("Write unit tests");
|
||||||
|
expect(task.description).toBe("Create comprehensive test coverage for new features");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should update task properties", () => {
|
||||||
|
const task = TaskModel.create({
|
||||||
|
name: "Initial task"
|
||||||
|
});
|
||||||
|
|
||||||
|
task.update({
|
||||||
|
name: "Updated task",
|
||||||
|
description: "Updated description"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(task.name).toBe("Updated task");
|
||||||
|
expect(task.description).toBe("Updated description");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should have unique IDs for different tasks", () => {
|
||||||
|
const task1 = TaskModel.create({ name: "Task 1" });
|
||||||
|
const task2 = TaskModel.create({ name: "Task 2" });
|
||||||
|
|
||||||
|
expect(task1.id).not.toBe(task2.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("RoleModel", () => {
|
||||||
|
test("should create a role with tasks", () => {
|
||||||
|
const role = RoleModel.create({
|
||||||
|
title: "API Engineer",
|
||||||
|
summary: "Designs and implements REST APIs"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(role.title).toBe("API Engineer");
|
||||||
|
expect(role.summary).toBe("Designs and implements REST APIs");
|
||||||
|
expect(role.tasks).toHaveLength(0);
|
||||||
|
expect(role.id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and remove tasks", () => {
|
||||||
|
const role = RoleModel.create({
|
||||||
|
title: "Backend Developer"
|
||||||
|
});
|
||||||
|
|
||||||
|
role.addTask({ name: "Design database schema" });
|
||||||
|
role.addTask({ name: "Implement API endpoints" });
|
||||||
|
|
||||||
|
expect(role.tasks).toHaveLength(2);
|
||||||
|
expect((role.tasks[0] as any).name).toBe("Design database schema");
|
||||||
|
expect((role.tasks[1] as any).name ).toBe("Implement API endpoints");
|
||||||
|
|
||||||
|
// Remove a task
|
||||||
|
const taskToRemove = role.tasks[0];
|
||||||
|
role.removeTask(taskToRemove);
|
||||||
|
|
||||||
|
expect(role.tasks).toHaveLength(1);
|
||||||
|
expect((role.tasks[0] as any).name).toBe("Implement API endpoints");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks through view", () => {
|
||||||
|
const role = RoleModel.create({
|
||||||
|
title: "Frontend Developer"
|
||||||
|
});
|
||||||
|
|
||||||
|
role.addTask({ name: "Build components" });
|
||||||
|
role.addTask({ name: "Write tests" });
|
||||||
|
|
||||||
|
const allTasks = role.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(2);
|
||||||
|
expect(allTasks[0].name).toBe("Build components");
|
||||||
|
expect(allTasks[1].name).toBe("Write tests");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("FieldModel", () => {
|
||||||
|
test("should create a field with roles", () => {
|
||||||
|
const field = FieldModel.create({
|
||||||
|
name: "Backend Development",
|
||||||
|
description: "Server-side application development"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(field.name).toBe("Backend Development");
|
||||||
|
expect(field.description).toBe("Server-side application development");
|
||||||
|
expect(field.roles).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and remove roles", () => {
|
||||||
|
const field = FieldModel.create({
|
||||||
|
name: "Frontend Development"
|
||||||
|
});
|
||||||
|
|
||||||
|
field.addRole({ title: "React Developer" });
|
||||||
|
field.addRole({ title: "Vue Developer" });
|
||||||
|
|
||||||
|
expect(field.roles).toHaveLength(2);
|
||||||
|
expect(field.roles[0].title).toBe("React Developer");
|
||||||
|
expect(field.roles[1].title).toBe("Vue Developer");
|
||||||
|
|
||||||
|
const roleToRemove = field.roles[0];
|
||||||
|
field.removeRole(roleToRemove);
|
||||||
|
|
||||||
|
expect(field.roles).toHaveLength(1);
|
||||||
|
expect(field.roles[0].title).toBe("Vue Developer");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks from nested roles", () => {
|
||||||
|
const field = FieldModel.create({
|
||||||
|
name: "Full Stack Development"
|
||||||
|
});
|
||||||
|
|
||||||
|
field.addRole({ title: "Frontend Developer" });
|
||||||
|
field.addRole({ title: "Backend Developer" });
|
||||||
|
|
||||||
|
// Add tasks to roles
|
||||||
|
field.roles[0].addTask({ name: "Build UI components" });
|
||||||
|
field.roles[0].addTask({ name: "Handle user interactions" });
|
||||||
|
field.roles[1].addTask({ name: "Design APIs" });
|
||||||
|
|
||||||
|
const allTasks = field.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(3);
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Build UI components");
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Handle user interactions");
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Design APIs");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("ProfessionModel", () => {
|
||||||
|
test("should create a profession with fields", () => {
|
||||||
|
const profession = ProfessionModel.create({
|
||||||
|
name: "Software Engineering",
|
||||||
|
description: "Building software systems and applications"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(profession.name).toBe("Software Engineering");
|
||||||
|
expect(profession.description).toBe("Building software systems and applications");
|
||||||
|
expect(profession.fields).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and remove fields", () => {
|
||||||
|
const profession = ProfessionModel.create({
|
||||||
|
name: "Web Development"
|
||||||
|
});
|
||||||
|
|
||||||
|
profession.addField({ name: "Frontend" });
|
||||||
|
profession.addField({ name: "Backend" });
|
||||||
|
|
||||||
|
expect(profession.fields).toHaveLength(2);
|
||||||
|
expect(profession.fields[0].name).toBe("Frontend");
|
||||||
|
expect(profession.fields[1].name).toBe("Backend");
|
||||||
|
|
||||||
|
const fieldToRemove = profession.fields[0];
|
||||||
|
profession.removeField(fieldToRemove);
|
||||||
|
|
||||||
|
expect(profession.fields).toHaveLength(1);
|
||||||
|
expect(profession.fields[0].name).toBe("Backend");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks from nested hierarchy", () => {
|
||||||
|
const profession = ProfessionModel.create({
|
||||||
|
name: "Software Engineering"
|
||||||
|
});
|
||||||
|
|
||||||
|
profession.addField({ name: "Backend" });
|
||||||
|
profession.fields[0].addRole({ title: "API Developer" });
|
||||||
|
profession.fields[0].roles[0].addTask({ name: "Design REST endpoints" });
|
||||||
|
profession.fields[0].roles[0].addTask({ name: "Implement authentication" });
|
||||||
|
|
||||||
|
const allTasks = profession.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(2);
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Design REST endpoints");
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Implement authentication");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("IndustryModel", () => {
|
||||||
|
test("should create an industry with professions", () => {
|
||||||
|
const industry = IndustryModel.create({
|
||||||
|
name: "Software",
|
||||||
|
description: "Software development and technology"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(industry.name).toBe("Software");
|
||||||
|
expect(industry.description).toBe("Software development and technology");
|
||||||
|
expect(industry.professions).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and remove professions", () => {
|
||||||
|
const industry = IndustryModel.create({
|
||||||
|
name: "Technology"
|
||||||
|
});
|
||||||
|
|
||||||
|
industry.addProfession({ name: "Software Engineering" });
|
||||||
|
industry.addProfession({ name: "Data Science" });
|
||||||
|
|
||||||
|
expect(industry.professions).toHaveLength(2);
|
||||||
|
expect(industry.professions[0].name).toBe("Software Engineering");
|
||||||
|
expect(industry.professions[1].name).toBe("Data Science");
|
||||||
|
|
||||||
|
// Remove a profession
|
||||||
|
const professionToRemove = industry.professions[0];
|
||||||
|
industry.removeProfession(professionToRemove);
|
||||||
|
|
||||||
|
expect(industry.professions).toHaveLength(1);
|
||||||
|
expect(industry.professions[0].name).toBe("Data Science");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks from nested hierarchy", () => {
|
||||||
|
const industry = IndustryModel.create({
|
||||||
|
name: "Software"
|
||||||
|
});
|
||||||
|
|
||||||
|
industry.addProfession({ name: "Web Development" });
|
||||||
|
industry.professions[0].addField({ name: "Frontend" });
|
||||||
|
industry.professions[0].fields[0].addRole({ title: "React Developer" });
|
||||||
|
industry.professions[0].fields[0].roles[0].addTask({ name: "Build components" });
|
||||||
|
industry.professions[0].fields[0].roles[0].addTask({ name: "Manage state" });
|
||||||
|
|
||||||
|
const allTasks = industry.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(2);
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Build components");
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Manage state");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("DomainModel", () => {
|
||||||
|
test("should create a domain with industries", () => {
|
||||||
|
const domain = DomainModel.create({
|
||||||
|
name: "STEM",
|
||||||
|
description: "Science, Technology, Engineering, and Mathematics"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(domain.name).toBe("STEM");
|
||||||
|
expect(domain.description).toBe("Science, Technology, Engineering, and Mathematics");
|
||||||
|
expect(domain.industries).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and remove industries", () => {
|
||||||
|
const domain = DomainModel.create({
|
||||||
|
name: "Technology"
|
||||||
|
});
|
||||||
|
|
||||||
|
domain.addIndustry({ name: "Software" });
|
||||||
|
domain.addIndustry({ name: "Hardware" });
|
||||||
|
|
||||||
|
expect(domain.industries).toHaveLength(2);
|
||||||
|
expect(domain.industries[0].name).toBe("Software");
|
||||||
|
expect(domain.industries[1].name).toBe("Hardware");
|
||||||
|
|
||||||
|
const industryToRemove = domain.industries[0];
|
||||||
|
domain.removeIndustry(industryToRemove);
|
||||||
|
|
||||||
|
expect(domain.industries).toHaveLength(1);
|
||||||
|
expect(domain.industries[0].name).toBe("Hardware");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks from nested hierarchy", () => {
|
||||||
|
const domain = DomainModel.create({
|
||||||
|
name: "STEM"
|
||||||
|
});
|
||||||
|
|
||||||
|
domain.addIndustry({ name: "Software" });
|
||||||
|
domain.industries[0].addProfession({ name: "Software Engineering" });
|
||||||
|
domain.industries[0].professions[0].addField({ name: "Backend" });
|
||||||
|
domain.industries[0].professions[0].fields[0].addRole({ title: "API Engineer" });
|
||||||
|
domain.industries[0].professions[0].fields[0].roles[0].addTask({ name: "Design REST endpoints" });
|
||||||
|
|
||||||
|
const allTasks = domain.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(1);
|
||||||
|
expect(allTasks[0].name).toBe("Design REST endpoints");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Enterprise", () => {
|
||||||
|
let store: IRootStore;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = Enterprise.create({});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should create an empty root store", () => {
|
||||||
|
expect(store.domains).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add domains", () => {
|
||||||
|
store.addDomain({ name: "STEM" });
|
||||||
|
store.addDomain({ name: "Arts" });
|
||||||
|
|
||||||
|
expect(store.domains).toHaveLength(2);
|
||||||
|
expect(store.domains[0].name).toBe("STEM");
|
||||||
|
expect(store.domains[1].name).toBe("Arts");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return all tasks from entire hierarchy", () => {
|
||||||
|
store.addDomain({ name: "STEM" });
|
||||||
|
store.domains[0].addIndustry({ name: "Software" });
|
||||||
|
store.domains[0].industries[0].addProfession({ name: "Software Engineering" });
|
||||||
|
store.domains[0].industries[0].professions[0].addField({ name: "Backend" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].addRole({ title: "API Engineer" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Design REST endpoints" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Implement authentication" });
|
||||||
|
|
||||||
|
const allTasks = store.allTasks;
|
||||||
|
expect(allTasks).toHaveLength(2);
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Design REST endpoints");
|
||||||
|
expect(allTasks.map(t => t.name)).toContain("Implement authentication");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Complete Hierarchy Integration", () => {
|
||||||
|
test("should create and manipulate a complete 6-layer hierarchy", () => {
|
||||||
|
const store = Enterprise.create({});
|
||||||
|
|
||||||
|
// Build the complete hierarchy as shown in the example
|
||||||
|
store.addDomain({ name: "STEM" });
|
||||||
|
store.domains[0].addIndustry({ name: "Software" });
|
||||||
|
store.domains[0].industries[0].addProfession({ name: "Software Engineering" });
|
||||||
|
store.domains[0].industries[0].professions[0].addField({ name: "Backend" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].addRole({ title: "API Engineer" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Design REST endpoints" });
|
||||||
|
|
||||||
|
expect(store.domains).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].fields).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].fields[0].roles).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].fields[0].roles[0].tasks).toHaveLength(1);
|
||||||
|
|
||||||
|
// Verify data integrity through the hierarchy
|
||||||
|
const task = store.domains[0].industries[0].professions[0].fields[0].roles[0].tasks[0];
|
||||||
|
expect(task.name).toBe("Design REST endpoints");
|
||||||
|
|
||||||
|
expect(store.allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[0].allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].fields[0].allTasks).toHaveLength(1);
|
||||||
|
|
||||||
|
// Add more tasks and verify aggregation
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Implement authentication" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].addRole({ title: "Database Engineer" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[1].addTask({ name: "Design database schema" });
|
||||||
|
|
||||||
|
expect(store.allTasks).toHaveLength(3);
|
||||||
|
expect(store.domains[0].industries[0].professions[0].fields[0].allTasks).toHaveLength(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle multiple parallel hierarchies", () => {
|
||||||
|
const store = Enterprise.create({});
|
||||||
|
|
||||||
|
store.addDomain({ name: "STEM" });
|
||||||
|
store.domains[0].addIndustry({ name: "Software" });
|
||||||
|
store.domains[0].industries[0].addProfession({ name: "Web Development" });
|
||||||
|
store.domains[0].industries[0].professions[0].addField({ name: "Frontend" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].addRole({ title: "React Developer" });
|
||||||
|
store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Build components" });
|
||||||
|
|
||||||
|
// Create second hierarchy branch
|
||||||
|
store.addDomain({ name: "Arts" });
|
||||||
|
store.domains[1].addIndustry({ name: "Digital Media" });
|
||||||
|
store.domains[1].industries[0].addProfession({ name: "Graphic Design" });
|
||||||
|
store.domains[1].industries[0].professions[0].addField({ name: "Web Design" });
|
||||||
|
store.domains[1].industries[0].professions[0].fields[0].addRole({ title: "UI Designer" });
|
||||||
|
store.domains[1].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Create mockups" });
|
||||||
|
|
||||||
|
expect(store.domains).toHaveLength(2);
|
||||||
|
expect(store.allTasks).toHaveLength(2);
|
||||||
|
expect(store.allTasks.map(t => t.name)).toContain("Build components");
|
||||||
|
expect(store.allTasks.map(t => t.name)).toContain("Create mockups");
|
||||||
|
|
||||||
|
// Verify each domain has its own tasks
|
||||||
|
expect(store.domains[0].allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[1].allTasks).toHaveLength(1);
|
||||||
|
expect(store.domains[0].allTasks[0].name).toBe("Build components");
|
||||||
|
expect(store.domains[1].allTasks[0].name).toBe("Create mockups");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("CRUD Operations", () => {
|
||||||
|
test("should support task updates and removal", () => {
|
||||||
|
const role = RoleModel.create({ title: "Developer" });
|
||||||
|
role.addTask({ name: "Initial task", description: "Initial description" });
|
||||||
|
|
||||||
|
const task = role.tasks[0];
|
||||||
|
const originalId = task.id;
|
||||||
|
|
||||||
|
task.update({ name: "Updated task", description: "Updated description" });
|
||||||
|
expect(task.name).toBe("Updated task");
|
||||||
|
expect(task.description).toBe("Updated description");
|
||||||
|
expect(task.id).toBe(originalId); // ID should remain the same
|
||||||
|
|
||||||
|
// Remove task through parent
|
||||||
|
expect(role.tasks).toHaveLength(1);
|
||||||
|
role.removeTask(task);
|
||||||
|
expect(role.tasks).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should support role removal", () => {
|
||||||
|
const field = FieldModel.create({ name: "Development" });
|
||||||
|
field.addRole({ title: "Developer" });
|
||||||
|
|
||||||
|
expect(field.roles).toHaveLength(1);
|
||||||
|
const role = field.roles[0];
|
||||||
|
field.removeRole(role);
|
||||||
|
expect(field.roles).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should support field removal", () => {
|
||||||
|
const profession = ProfessionModel.create({ name: "Engineering" });
|
||||||
|
profession.addField({ name: "Software" });
|
||||||
|
|
||||||
|
expect(profession.fields).toHaveLength(1);
|
||||||
|
const field = profession.fields[0];
|
||||||
|
profession.removeField(field);
|
||||||
|
expect(profession.fields).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should support profession removal", () => {
|
||||||
|
const industry = IndustryModel.create({ name: "Tech" });
|
||||||
|
industry.addProfession({ name: "Software Engineering" });
|
||||||
|
|
||||||
|
expect(industry.professions).toHaveLength(1);
|
||||||
|
const profession = industry.professions[0];
|
||||||
|
industry.removeProfession(profession);
|
||||||
|
expect(industry.professions).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should support industry removal", () => {
|
||||||
|
const domain = DomainModel.create({ name: "STEM" });
|
||||||
|
domain.addIndustry({ name: "Software" });
|
||||||
|
|
||||||
|
expect(domain.industries).toHaveLength(1);
|
||||||
|
const industry = domain.industries[0];
|
||||||
|
domain.removeIndustry(industry);
|
||||||
|
expect(domain.industries).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
203
lib/agent-wrapper.ts
Normal file
203
lib/agent-wrapper.ts
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
import { Agent, StreamedRunResult } from '@openai/agents';
|
||||||
|
import HierarchyGenerator, { GenerationParams } from './components/hierarchy-generator';
|
||||||
|
import TemplateManager, { DomainTemplate } from './components/template-manager';
|
||||||
|
import OutputFormatter, { OutputOptions, FormattedOutput } from './components/output-formatter';
|
||||||
|
|
||||||
|
export interface AgentConfig {
|
||||||
|
name: string;
|
||||||
|
instructions: string;
|
||||||
|
model?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HierarchyGenerationOptions extends GenerationParams {
|
||||||
|
outputFormat?: OutputOptions;
|
||||||
|
templateKey?: string;
|
||||||
|
stream?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HierarchyAgent {
|
||||||
|
private agent: Agent;
|
||||||
|
private generator: HierarchyGenerator;
|
||||||
|
private templateManager: TemplateManager;
|
||||||
|
private outputFormatter: OutputFormatter;
|
||||||
|
|
||||||
|
constructor(config: AgentConfig) {
|
||||||
|
this.agent = new Agent({
|
||||||
|
name: config.name,
|
||||||
|
instructions: config.instructions,
|
||||||
|
model: config.model || 'gpt-4o-mini'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.generator = new HierarchyGenerator(this.agent);
|
||||||
|
this.templateManager = new TemplateManager();
|
||||||
|
this.outputFormatter = new OutputFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateHierarchy(options: HierarchyGenerationOptions): Promise<FormattedOutput | StreamedRunResult> {
|
||||||
|
let template: DomainTemplate;
|
||||||
|
|
||||||
|
if (options.templateKey) {
|
||||||
|
template = this.templateManager.getTemplate(options.templateKey);
|
||||||
|
if (!template) {
|
||||||
|
throw new Error(`Template not found: ${options.templateKey}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create a default template for the domain
|
||||||
|
const version = options.version || 'v2';
|
||||||
|
template = this.templateManager.createCustomTemplate(
|
||||||
|
`${options.domain}-${version}`,
|
||||||
|
options.domain,
|
||||||
|
version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const generationParams: GenerationParams = {
|
||||||
|
domain: options.domain,
|
||||||
|
complexity: options.complexity || 'medium',
|
||||||
|
includeSkills: options.includeSkills ?? true,
|
||||||
|
includeTools: options.includeTools ?? true,
|
||||||
|
includeExamples: options.includeExamples ?? true,
|
||||||
|
stream: options.stream
|
||||||
|
};
|
||||||
|
|
||||||
|
const content = await this.generator.generateFromTemplate(template, generationParams);
|
||||||
|
|
||||||
|
// If streaming, return the stream directly
|
||||||
|
if (options.stream && content instanceof Object && 'toStream' in content) {
|
||||||
|
return content as StreamedRunResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputOptions = options.outputFormat || this.outputFormatter.getDefaultOptions();
|
||||||
|
const formattedOutput = this.outputFormatter.formatOutput(
|
||||||
|
content as string,
|
||||||
|
options.domain,
|
||||||
|
template.version,
|
||||||
|
outputOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
return formattedOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New method for streaming with enhanced visibility
|
||||||
|
async generateHierarchyWithStreaming(
|
||||||
|
options: HierarchyGenerationOptions,
|
||||||
|
onStreamEvent?: (event: any) => void
|
||||||
|
): Promise<FormattedOutput> {
|
||||||
|
let template: DomainTemplate;
|
||||||
|
|
||||||
|
if (options.templateKey) {
|
||||||
|
template = this.templateManager.getTemplate(options.templateKey);
|
||||||
|
if (!template) {
|
||||||
|
throw new Error(`Template not found: ${options.templateKey}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create a default template for the domain
|
||||||
|
const version = options.version || 'v2';
|
||||||
|
template = this.templateManager.createCustomTemplate(
|
||||||
|
`${options.domain}-${version}`,
|
||||||
|
options.domain,
|
||||||
|
version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const generationParams: GenerationParams = {
|
||||||
|
domain: options.domain,
|
||||||
|
complexity: options.complexity || 'medium',
|
||||||
|
includeSkills: options.includeSkills ?? true,
|
||||||
|
includeTools: options.includeTools ?? true,
|
||||||
|
includeExamples: options.includeExamples ?? true
|
||||||
|
};
|
||||||
|
|
||||||
|
const content = await this.generator.generateFromTemplateWithStreaming(
|
||||||
|
template,
|
||||||
|
generationParams,
|
||||||
|
onStreamEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
// Format the output
|
||||||
|
const outputOptions = options.outputFormat || this.outputFormatter.getDefaultOptions();
|
||||||
|
const formattedOutput = this.outputFormatter.formatOutput(
|
||||||
|
content,
|
||||||
|
options.domain,
|
||||||
|
template.version,
|
||||||
|
outputOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
return formattedOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateExample(
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2' = 'v2',
|
||||||
|
complexity: 'simple' | 'medium' | 'complex' = 'medium'
|
||||||
|
): Promise<FormattedOutput> {
|
||||||
|
return this.generateHierarchy({
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
complexity,
|
||||||
|
includeSkills: true,
|
||||||
|
includeTools: true,
|
||||||
|
includeExamples: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template management methods
|
||||||
|
getAvailableTemplates(): DomainTemplate[] {
|
||||||
|
return this.templateManager.getAllTemplates();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplatesByDomain(domain: string): DomainTemplate[] {
|
||||||
|
return this.templateManager.getTemplatesByDomain(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplatesByVersion(version: 'v1' | 'v2'): DomainTemplate[] {
|
||||||
|
return this.templateManager.getTemplatesByVersion(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCustomTemplate(key: string, template: DomainTemplate): void {
|
||||||
|
this.templateManager.addTemplate(key, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation and optimization methods
|
||||||
|
async validateHierarchy(hierarchyData: any): Promise<boolean> {
|
||||||
|
// TODO: Implement validation logic using the agent
|
||||||
|
// Could validate structure, naming conventions, completeness, etc.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async optimizeHierarchy(hierarchyData: any): Promise<any> {
|
||||||
|
// TODO: Implement optimization logic using the agent
|
||||||
|
// Could suggest improvements, fill gaps, optimize structure, etc.
|
||||||
|
return hierarchyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Batch generation methods
|
||||||
|
async generateMultipleExamples(
|
||||||
|
domains: string[],
|
||||||
|
version: 'v1' | 'v2' = 'v2',
|
||||||
|
outputFormat?: OutputOptions
|
||||||
|
): Promise<FormattedOutput[]> {
|
||||||
|
const results: FormattedOutput[] = [];
|
||||||
|
|
||||||
|
for (const domain of domains) {
|
||||||
|
try {
|
||||||
|
const result = await this.generateHierarchy({
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
complexity: 'medium',
|
||||||
|
includeSkills: true,
|
||||||
|
includeTools: true,
|
||||||
|
includeExamples: true,
|
||||||
|
outputFormat
|
||||||
|
});
|
||||||
|
results.push(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error generating example for ${domain}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HierarchyAgent;
|
115
lib/components/hierarchy-generator.ts
Normal file
115
lib/components/hierarchy-generator.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import { Agent, run, StreamedRunResult } from '@openai/agents';
|
||||||
|
|
||||||
|
export interface HierarchyTemplate {
|
||||||
|
version: 'v1' | 'v2';
|
||||||
|
structure: string[];
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerationParams {
|
||||||
|
domain: string;
|
||||||
|
complexity: 'simple' | 'medium' | 'complex';
|
||||||
|
includeSkills: boolean;
|
||||||
|
includeTools: boolean;
|
||||||
|
includeExamples: boolean;
|
||||||
|
stream?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HierarchyGenerator {
|
||||||
|
private agent: Agent;
|
||||||
|
|
||||||
|
constructor(agent: Agent) {
|
||||||
|
this.agent = agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateFromTemplate(template: HierarchyTemplate, params: GenerationParams): Promise<string | StreamedRunResult> {
|
||||||
|
const prompt = this.buildPrompt(template, params);
|
||||||
|
|
||||||
|
if (params.stream) {
|
||||||
|
return await run(this.agent, prompt, { stream: true });
|
||||||
|
} else {
|
||||||
|
const result = await run(this.agent, prompt);
|
||||||
|
return result.finalOutput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to stream and collect final output
|
||||||
|
async generateFromTemplateWithStreaming(
|
||||||
|
template: HierarchyTemplate,
|
||||||
|
params: GenerationParams,
|
||||||
|
onStreamEvent?: (event: any) => void
|
||||||
|
): Promise<string> {
|
||||||
|
const prompt = this.buildPrompt(template, params);
|
||||||
|
console.log('🔄 Starting hierarchy generation...');
|
||||||
|
|
||||||
|
const stream = await run(this.agent, prompt, { stream: true });
|
||||||
|
let content = '';
|
||||||
|
|
||||||
|
for await (const event of stream) {
|
||||||
|
if (event.type === 'raw_model_stream_event' && event.data.delta) {
|
||||||
|
// console.log(event.data.delta)
|
||||||
|
content += event.delta;
|
||||||
|
process.stdout.write(event.data.delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'agent_updated_stream_event') {
|
||||||
|
console.log(`\n📝 Agent: ${event.agent.name} is processing...`);
|
||||||
|
} else if (event.type === 'run_item_stream_event') {
|
||||||
|
if (event.item.type === 'tool_call_item') {
|
||||||
|
console.log('\n🔧 Tool being called...');
|
||||||
|
} else if (event.item.type === 'message_output_item') {
|
||||||
|
console.log('\n💬 Generating response...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow custom event handling
|
||||||
|
if (onStreamEvent) {
|
||||||
|
onStreamEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n✅ Hierarchy generation complete!');
|
||||||
|
return stream.finalOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildPrompt(template: HierarchyTemplate, params: GenerationParams): string {
|
||||||
|
const structureDescription = template.version === 'v1'
|
||||||
|
? 'Domain → Specialization → Role → Responsibility'
|
||||||
|
: 'Domain → Industry → Profession → Field → Role → Task';
|
||||||
|
|
||||||
|
const importStatement = template.version === 'v1'
|
||||||
|
? 'import { Enterprise, DomainModel, SpecializationModel, RoleModel, ResponsibilityModel } from "../../lib/v1";'
|
||||||
|
: 'import { Enterprise, DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel } from "../../lib/v2";';
|
||||||
|
|
||||||
|
return `
|
||||||
|
Generate ONLY TypeScript code for a professional hierarchy in the ${params.domain} domain using the ${template.version} structure.
|
||||||
|
|
||||||
|
Structure: ${structureDescription}
|
||||||
|
Complexity Level: ${params.complexity}
|
||||||
|
${params.includeSkills ? '✓ Include relevant skills and competencies' : ''}
|
||||||
|
${params.includeTools ? '✓ Include tools and technologies' : ''}
|
||||||
|
${params.includeExamples ? '✓ Include practical examples and use cases' : ''}
|
||||||
|
|
||||||
|
IMPORTANT: Output ONLY valid TypeScript code. Do not include any markdown, explanations, or comments outside of TypeScript comments.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
1. Start with the import statement: ${importStatement}
|
||||||
|
2. Create a realistic, comprehensive hierarchy using MobX State Tree models
|
||||||
|
3. Use appropriate professional terminology
|
||||||
|
4. Ensure logical relationships between levels
|
||||||
|
5. ${params.complexity === 'complex' ? 'Include multiple branches and detailed attributes' :
|
||||||
|
params.complexity === 'medium' ? 'Include moderate detail with key attributes' :
|
||||||
|
'Keep it simple with essential elements only'}
|
||||||
|
|
||||||
|
The code should demonstrate:
|
||||||
|
- Creating the hierarchy structure using the imported models
|
||||||
|
- Adding relevant attributes (skills, tools, examples)
|
||||||
|
- Basic operations (create, read, update)
|
||||||
|
- Real-world application examples as TypeScript code
|
||||||
|
|
||||||
|
Output format: Pure TypeScript code only, no markdown or explanations.
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HierarchyGenerator;
|
278
lib/components/output-formatter.ts
Normal file
278
lib/components/output-formatter.ts
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
export interface OutputOptions {
|
||||||
|
format: 'typescript' | 'markdown' | 'json' | 'yaml';
|
||||||
|
includeMetadata: boolean;
|
||||||
|
includeTimestamp: boolean;
|
||||||
|
includeComments: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FormattedOutput {
|
||||||
|
content: string;
|
||||||
|
filename: string;
|
||||||
|
extension: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OutputFormatter {
|
||||||
|
formatOutput(
|
||||||
|
content: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: OutputOptions
|
||||||
|
): FormattedOutput {
|
||||||
|
switch (options.format) {
|
||||||
|
case 'typescript':
|
||||||
|
return this.formatTypeScript(content, domain, version, options);
|
||||||
|
case 'markdown':
|
||||||
|
return this.formatMarkdown(content, domain, version, options);
|
||||||
|
case 'json':
|
||||||
|
return this.formatJSON(content, domain, version, options);
|
||||||
|
case 'yaml':
|
||||||
|
return this.formatYAML(content, domain, version, options);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported format: ${options.format}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatTypeScript(
|
||||||
|
content: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: OutputOptions
|
||||||
|
): FormattedOutput {
|
||||||
|
const header = options.includeComments ? `/**
|
||||||
|
* ${domain} Professional Hierarchy Example
|
||||||
|
* Generated using OpenAI Agents SDK and Sumpin Professional Hierarchy Models
|
||||||
|
* Model Version: ${version} (${version === 'v1' ? '4-layer' : '6-layer'} hierarchy)
|
||||||
|
* ${options.includeTimestamp ? `Generated on: ${new Date().toISOString()}` : ''}
|
||||||
|
*/
|
||||||
|
|
||||||
|
` : '';
|
||||||
|
|
||||||
|
const imports = `import {
|
||||||
|
Enterprise,
|
||||||
|
${version === 'v1' ? 'DomainModel, SpecializationModel, RoleModel, ResponsibilityModel' : 'DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel'}
|
||||||
|
} from "../../lib/${version}";
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
const cleanedContent = this.extractTypeScriptCode(content);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: header + imports + cleanedContent,
|
||||||
|
filename: `${domain.toLowerCase()}-hierarchy-example`,
|
||||||
|
extension: 'ts',
|
||||||
|
metadata: {
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
generatedAt: options.includeTimestamp ? new Date().toISOString() : undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractTypeScriptCode(content: string): string {
|
||||||
|
let cleaned = content;
|
||||||
|
|
||||||
|
cleaned = cleaned.replace(/^#{1,6}\s+.*$/gm, '');
|
||||||
|
|
||||||
|
cleaned = cleaned.replace(/\*\*([^*]+)\*\*/g, '$1');
|
||||||
|
cleaned = cleaned.replace(/\*([^*]+)\*/g, '$1');
|
||||||
|
|
||||||
|
// Remove markdown lists that aren't TypeScript code
|
||||||
|
cleaned = cleaned.replace(/^[\s]*[-*+]\s+\*\*([^*]+)\*\*$/gm, '');
|
||||||
|
cleaned = cleaned.replace(/^[\s]*[-*+]\s+([^:]+):$/gm, '');
|
||||||
|
|
||||||
|
// Extract TypeScript code blocks
|
||||||
|
const codeBlockRegex = /```typescript\s*([\s\S]*?)```/g;
|
||||||
|
const codeBlocks = [];
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = codeBlockRegex.exec(content)) !== null) {
|
||||||
|
codeBlocks.push(match[1].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found code blocks, use them
|
||||||
|
if (codeBlocks.length > 0) {
|
||||||
|
return codeBlocks.join('\n\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, try to extract TypeScript-like content
|
||||||
|
const lines = cleaned.split('\n');
|
||||||
|
const tsLines = [];
|
||||||
|
let inCodeSection = false;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
|
||||||
|
// Skip empty lines and markdown-like content
|
||||||
|
if (!trimmed ||
|
||||||
|
trimmed.startsWith('#') ||
|
||||||
|
trimmed.startsWith('*') ||
|
||||||
|
trimmed.startsWith('-') ||
|
||||||
|
trimmed.includes('Below is') ||
|
||||||
|
trimmed.includes('Here\'s') ||
|
||||||
|
trimmed.includes('TypeScript Code') ||
|
||||||
|
trimmed.includes('Professional Hierarchy')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for TypeScript patterns
|
||||||
|
if (trimmed.includes('interface ') ||
|
||||||
|
trimmed.includes('class ') ||
|
||||||
|
trimmed.includes('type ') ||
|
||||||
|
trimmed.includes('const ') ||
|
||||||
|
trimmed.includes('let ') ||
|
||||||
|
trimmed.includes('var ') ||
|
||||||
|
trimmed.includes('function ') ||
|
||||||
|
trimmed.includes('export ') ||
|
||||||
|
trimmed.includes('import ') ||
|
||||||
|
trimmed.includes('{') ||
|
||||||
|
trimmed.includes('}') ||
|
||||||
|
trimmed.includes(';') ||
|
||||||
|
inCodeSection) {
|
||||||
|
|
||||||
|
tsLines.push(line);
|
||||||
|
inCodeSection = true;
|
||||||
|
|
||||||
|
// End code section on certain patterns
|
||||||
|
if (trimmed === '}' && !line.includes(',')) {
|
||||||
|
inCodeSection = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tsLines.join('\n').trim() || cleaned.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatMarkdown(
|
||||||
|
content: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: OutputOptions
|
||||||
|
): FormattedOutput {
|
||||||
|
const header = `# ${domain.charAt(0).toUpperCase() + domain.slice(1)} Professional Hierarchy Example
|
||||||
|
|
||||||
|
Generated using OpenAI Agents SDK and Sumpin Professional Hierarchy Models
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This example demonstrates a ${version} professional hierarchy model for the ${domain} domain.
|
||||||
|
|
||||||
|
**Model Version:** ${version} (${version === 'v1' ? '4-layer' : '6-layer'} hierarchy)
|
||||||
|
${options.includeTimestamp ? `**Generated on:** ${new Date().toISOString()}` : ''}
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
${version === 'v1' ? 'Domain → Specialization → Role → Responsibility' : 'Domain → Industry → Profession → Field → Role → Task'}
|
||||||
|
|
||||||
|
## Generated Content
|
||||||
|
|
||||||
|
\`\`\`typescript
|
||||||
|
${content}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use this example:
|
||||||
|
|
||||||
|
1. Ensure you have the required dependencies installed:
|
||||||
|
\`\`\`bash
|
||||||
|
bun add mobx-state-tree mobx uuid
|
||||||
|
bun add -d @types/uuid
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
2. Run the example:
|
||||||
|
\`\`\`bash
|
||||||
|
bun run examples/generated/${domain.toLowerCase()}-hierarchy-example.ts
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
---
|
||||||
|
*This example was generated automatically and demonstrates best practices for professional hierarchy modeling.*
|
||||||
|
`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: header,
|
||||||
|
filename: `${domain.toLowerCase()}-hierarchy-example`,
|
||||||
|
extension: 'md',
|
||||||
|
metadata: {
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
generatedAt: options.includeTimestamp ? new Date().toISOString() : undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatJSON(
|
||||||
|
content: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: OutputOptions
|
||||||
|
): FormattedOutput {
|
||||||
|
const data = {
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
structure: version === 'v1'
|
||||||
|
? ['Domain', 'Specialization', 'Role', 'Responsibility']
|
||||||
|
: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task'],
|
||||||
|
generatedContent: content,
|
||||||
|
...(options.includeMetadata && {
|
||||||
|
metadata: {
|
||||||
|
generatedAt: options.includeTimestamp ? new Date().toISOString() : undefined,
|
||||||
|
generator: 'OpenAI Agents SDK + Sumpin',
|
||||||
|
hierarchyType: `${version === 'v1' ? '4' : '6'}-layer hierarchy`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: JSON.stringify(data, null, 2),
|
||||||
|
filename: `${domain.toLowerCase()}-hierarchy-example`,
|
||||||
|
extension: 'json',
|
||||||
|
metadata: data.metadata
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatYAML(
|
||||||
|
content: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: OutputOptions
|
||||||
|
): FormattedOutput {
|
||||||
|
const yamlContent = `domain: ${domain}
|
||||||
|
version: ${version}
|
||||||
|
structure:
|
||||||
|
${(version === 'v1'
|
||||||
|
? ['Domain', 'Specialization', 'Role', 'Responsibility']
|
||||||
|
: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task']
|
||||||
|
).map(item => ` - ${item}`).join('\n')}
|
||||||
|
|
||||||
|
generated_content: |
|
||||||
|
${content.split('\n').map(line => ` ${line}`).join('\n')}
|
||||||
|
|
||||||
|
${options.includeMetadata ? `metadata:
|
||||||
|
generated_at: ${options.includeTimestamp ? new Date().toISOString() : 'null'}
|
||||||
|
generator: "OpenAI Agents SDK + Sumpin"
|
||||||
|
hierarchy_type: "${version === 'v1' ? '4' : '6'}-layer hierarchy"` : ''}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: yamlContent,
|
||||||
|
filename: `${domain.toLowerCase()}-hierarchy-example`,
|
||||||
|
extension: 'yaml',
|
||||||
|
metadata: {
|
||||||
|
domain,
|
||||||
|
version,
|
||||||
|
generatedAt: options.includeTimestamp ? new Date().toISOString() : undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultOptions(): OutputOptions {
|
||||||
|
return {
|
||||||
|
format: 'typescript',
|
||||||
|
includeMetadata: true,
|
||||||
|
includeTimestamp: true,
|
||||||
|
includeComments: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OutputFormatter;
|
81
lib/components/template-manager.ts
Normal file
81
lib/components/template-manager.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { HierarchyTemplate } from './hierarchy-generator';
|
||||||
|
import v1Finance from "./templates/v1-finance.ts";
|
||||||
|
import v1Tech from "./templates/v1-tech.ts";
|
||||||
|
import v2Edu from "./templates/v2-edu.ts";
|
||||||
|
import v2Healthcare from "./templates/v2-healthcare.ts";
|
||||||
|
import v2Tech from "./templates/v2-tech.ts";
|
||||||
|
|
||||||
|
export interface DomainTemplate extends HierarchyTemplate {
|
||||||
|
domain: string;
|
||||||
|
commonSkills: string[];
|
||||||
|
commonTools: string[];
|
||||||
|
examples: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TemplateManager {
|
||||||
|
private templates: Map<string, DomainTemplate> = new Map();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.initializeDefaultTemplates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeDefaultTemplates() {
|
||||||
|
// V2 Templates (6-layer hierarchy)
|
||||||
|
this.addTemplate('technology-v2', v2Tech);
|
||||||
|
this.addTemplate('healthcare-v2', v2Healthcare);
|
||||||
|
this.addTemplate('education-v2', v2Edu);
|
||||||
|
|
||||||
|
// V1 Templates (4-layer hierarchy)
|
||||||
|
this.addTemplate('technology-v1', v1Tech);
|
||||||
|
this.addTemplate('finance-v1', v1Finance);
|
||||||
|
}
|
||||||
|
|
||||||
|
addTemplate(key: string, template: DomainTemplate): void {
|
||||||
|
this.templates.set(key, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplate(key: string): DomainTemplate | undefined {
|
||||||
|
return this.templates.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplatesByVersion(version: 'v1' | 'v2'): DomainTemplate[] {
|
||||||
|
return Array.from(this.templates.values()).filter(t => t.version === version);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplatesByDomain(domain: string): DomainTemplate[] {
|
||||||
|
return Array.from(this.templates.values()).filter(t =>
|
||||||
|
t.domain.toLowerCase().includes(domain.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllTemplates(): DomainTemplate[] {
|
||||||
|
return Array.from(this.templates.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
createCustomTemplate(
|
||||||
|
key: string,
|
||||||
|
domain: string,
|
||||||
|
version: 'v1' | 'v2',
|
||||||
|
options: Partial<DomainTemplate> = {}
|
||||||
|
): DomainTemplate {
|
||||||
|
const structure = version === 'v1'
|
||||||
|
? ['Domain', 'Specialization', 'Role', 'Responsibility']
|
||||||
|
: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task'];
|
||||||
|
|
||||||
|
const template: DomainTemplate = {
|
||||||
|
version,
|
||||||
|
domain,
|
||||||
|
structure,
|
||||||
|
description: `${domain} professional hierarchy`,
|
||||||
|
commonSkills: [],
|
||||||
|
commonTools: [],
|
||||||
|
examples: [],
|
||||||
|
...options
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addTemplate(key, template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TemplateManager;
|
9
lib/components/templates/v1-finance.ts
Normal file
9
lib/components/templates/v1-finance.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
version: 'v1',
|
||||||
|
domain: 'Finance',
|
||||||
|
structure: ['Domain', 'Specialization', 'Role', 'Responsibility'],
|
||||||
|
description: 'Simplified finance sector hierarchy',
|
||||||
|
commonSkills: ['Financial Analysis', 'Risk Assessment', 'Compliance', 'Reporting'],
|
||||||
|
commonTools: ['Excel', 'Financial Software', 'Analytics Tools', 'Reporting Systems'],
|
||||||
|
examples: ['Investment Banking', 'Corporate Finance', 'Risk Management', 'Accounting']
|
||||||
|
}
|
9
lib/components/templates/v1-tech.ts
Normal file
9
lib/components/templates/v1-tech.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
version: 'v1',
|
||||||
|
domain: 'Technology',
|
||||||
|
structure: ['Domain', 'Specialization', 'Role', 'Responsibility'],
|
||||||
|
description: 'Simplified technology sector hierarchy',
|
||||||
|
commonSkills: ['Programming', 'System Design', 'Testing', 'Documentation'],
|
||||||
|
commonTools: ['Code Editors', 'Version Control', 'Build Tools', 'Monitoring'],
|
||||||
|
examples: ['Web Development', 'Mobile Development', 'Backend Systems', 'Frontend UI']
|
||||||
|
}
|
9
lib/components/templates/v2-edu.ts
Normal file
9
lib/components/templates/v2-edu.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
version: 'v2',
|
||||||
|
domain: 'Education',
|
||||||
|
structure: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task'],
|
||||||
|
description: 'Comprehensive education sector hierarchy',
|
||||||
|
commonSkills: ['Teaching', 'Curriculum Development', 'Assessment', 'Student Engagement'],
|
||||||
|
commonTools: ['LMS', 'Educational Software', 'Assessment Tools', 'Communication Platforms'],
|
||||||
|
examples: ['K-12 Education', 'Higher Education', 'Corporate Training', 'Online Learning']
|
||||||
|
}
|
9
lib/components/templates/v2-healthcare.ts
Normal file
9
lib/components/templates/v2-healthcare.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
version: 'v2',
|
||||||
|
domain: 'Healthcare',
|
||||||
|
structure: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task'],
|
||||||
|
description: 'Comprehensive healthcare sector hierarchy',
|
||||||
|
commonSkills: ['Patient Care', 'Medical Knowledge', 'Communication', 'Empathy'],
|
||||||
|
commonTools: ['EMR Systems', 'Medical Devices', 'Diagnostic Tools', 'Communication Systems'],
|
||||||
|
examples: ['Clinical Care', 'Medical Research', 'Healthcare Administration', 'Public Health']
|
||||||
|
}
|
9
lib/components/templates/v2-tech.ts
Normal file
9
lib/components/templates/v2-tech.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
version: 'v2',
|
||||||
|
domain: 'Technology',
|
||||||
|
structure: ['Domain', 'Industry', 'Profession', 'Field', 'Role', 'Task'],
|
||||||
|
description: 'Comprehensive technology sector hierarchy',
|
||||||
|
commonSkills: ['Problem Solving', 'Critical Thinking', 'Communication', 'Collaboration'],
|
||||||
|
commonTools: ['Git', 'IDE', 'Testing Frameworks', 'Documentation Tools'],
|
||||||
|
examples: ['Software Development', 'DevOps', 'Data Science', 'Cybersecurity']
|
||||||
|
}
|
35
lib/hierarchy-model.ts
Normal file
35
lib/hierarchy-model.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { types } from "mobx-state-tree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reusable abstraction for a domain/sector hierarchy.
|
||||||
|
* Works for both v1 and v2
|
||||||
|
*/
|
||||||
|
export const HierarchyModel = types.model("HierarchyModel", {
|
||||||
|
version: types.string, // "v1" | "v2"
|
||||||
|
domain: types.string, // e.g. "Finance", "Technology"
|
||||||
|
structure: types.array(types.string), // ordered hierarchy labels
|
||||||
|
description: types.string, // plain-text description
|
||||||
|
commonSkills: types.array(types.string),
|
||||||
|
commonTools: types.array(types.string),
|
||||||
|
examples: types.array(types.string)
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ *
|
||||||
|
* Example usage
|
||||||
|
* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
// Create individual instances
|
||||||
|
// import { HierarchyModel } from "./hierarchy-model";
|
||||||
|
//
|
||||||
|
// const finance = HierarchyModel.create(v1Finance);
|
||||||
|
// const tech = HierarchyModel.create(v2Tech);
|
||||||
|
|
||||||
|
export const HierarchyStore = types
|
||||||
|
.model("HierarchyStore", {
|
||||||
|
items: types.map(HierarchyModel) // keyed by domain name
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
add(h: Instance<typeof HierarchyModel>) {
|
||||||
|
self.items.set(h.domain, h);
|
||||||
|
}
|
||||||
|
}));
|
4
lib/index.ts
Normal file
4
lib/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import v1 from './v1';
|
||||||
|
import v2 from './v2';
|
||||||
|
|
||||||
|
export { v1, v2 };
|
41
lib/v1.ts
Normal file
41
lib/v1.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { types } from "mobx-state-tree"
|
||||||
|
|
||||||
|
const Attribute = types.model("Attribute", {
|
||||||
|
name: types.string,
|
||||||
|
type: types.enumeration("AttributeType", ["Skill", "Tool", "Trait"]),
|
||||||
|
description: types.optional(types.string, "")
|
||||||
|
})
|
||||||
|
|
||||||
|
const Responsibility = types.model("Responsibility", {
|
||||||
|
title: types.string,
|
||||||
|
outcome: types.string,
|
||||||
|
requiredAttributes: types.array(Attribute)
|
||||||
|
})
|
||||||
|
|
||||||
|
const Role = types.model("Role", {
|
||||||
|
title: types.string,
|
||||||
|
responsibilities: types.array(Responsibility),
|
||||||
|
requiredAttributes: types.array(Attribute),
|
||||||
|
seniority: types.enumeration("Seniority", ["Intern", "Junior", "Mid", "Senior", "Lead", "Principal"])
|
||||||
|
})
|
||||||
|
|
||||||
|
// Specialization within a domain (e.g., cardiologist within medicine)
|
||||||
|
const Specialization = types.model("Specialization", {
|
||||||
|
name: types.string,
|
||||||
|
focus: types.string,
|
||||||
|
coreAttributes: types.array(Attribute),
|
||||||
|
roles: types.array(Role)
|
||||||
|
})
|
||||||
|
|
||||||
|
const Domain = types.model("Domain", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.optional(types.string, ""),
|
||||||
|
specializations: types.array(Specialization),
|
||||||
|
coreAttributes: types.array(Attribute)
|
||||||
|
})
|
||||||
|
|
||||||
|
const ProfessionModel = types.model("ProfessionModel", {
|
||||||
|
domains: types.array(Domain)
|
||||||
|
});
|
||||||
|
|
||||||
|
export { ProfessionModel, Domain, Specialization, Role, Responsibility, Attribute }
|
194
lib/v2.ts
Normal file
194
lib/v2.ts
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// Profession Hierarchy Model using mobx-state-tree (MST)
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// This file defines a generic, extensible hierarchy that captures the essence
|
||||||
|
// of professions. It intentionally separates concerns across six conceptual
|
||||||
|
// layers, from the broad Domain level down to atomic Tasks. Each layer owns
|
||||||
|
// its children through strongly‑typed arrays, enabling fine‑grained reactivity,
|
||||||
|
// traversal, and manipulation.
|
||||||
|
//
|
||||||
|
// Layering
|
||||||
|
// ┌ Domain – e.g. "STEM", "Arts", "Public Service"
|
||||||
|
// │ └ Industry – e.g. "Software", "Healthcare", "Finance"
|
||||||
|
// │ └ Profession – e.g. "Software Engineering", "Nursing"
|
||||||
|
// │ └ Field – e.g. "Backend", "Pediatrics"
|
||||||
|
// │ └ Role – e.g. "API Engineer", "Pediatric Nurse"
|
||||||
|
// │ └ Task – e.g. "Design REST endpoints", "Administer vaccine"
|
||||||
|
//
|
||||||
|
// Each model exposes actions to mutate its children as well as compositional
|
||||||
|
// views to rapidly surface nested information (e.g., all tasks under an
|
||||||
|
// Industry). Identifiers are UUID‑v4 strings to guarantee uniqueness across
|
||||||
|
// distributed systems.
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
import { types, Instance, SnapshotIn, getParent, destroy } from "mobx-state-tree";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
|
/* Utility --------------------------------------------------------------- */
|
||||||
|
const withId = <T extends Record<string, unknown>>(modelName: string, definition: T) =>
|
||||||
|
types.model(modelName, {
|
||||||
|
id: types.optional(types.identifier, uuidv4),
|
||||||
|
...definition
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Task ------------------------------------------------------------------ */
|
||||||
|
export const TaskModel = withId("Task", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.maybe(types.string)
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
update(attrs: Partial<SnapshotIn<typeof TaskModel>>) {
|
||||||
|
Object.assign(self, attrs);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Task extends Instance<typeof TaskModel> {}
|
||||||
|
|
||||||
|
/* Role ------------------------------------------------------------------ */
|
||||||
|
export const RoleModel = withId("Role", {
|
||||||
|
title: types.string,
|
||||||
|
summary: types.maybe(types.string),
|
||||||
|
tasks: types.optional(types.array(TaskModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addTask(task: SnapshotIn<typeof TaskModel>) {
|
||||||
|
self.tasks.push(TaskModel.create(task));
|
||||||
|
},
|
||||||
|
removeTask(task: Task) {
|
||||||
|
self.tasks.remove(task);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
get allTasks() {
|
||||||
|
return self.tasks.slice();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Role extends Instance<typeof RoleModel> {}
|
||||||
|
|
||||||
|
/* Field (Specialization) ------------------------------------------------- */
|
||||||
|
export const FieldModel = withId("Field", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.maybe(types.string),
|
||||||
|
roles: types.optional(types.array(RoleModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addRole(role: SnapshotIn<typeof RoleModel>) {
|
||||||
|
self.roles.push(RoleModel.create(role));
|
||||||
|
},
|
||||||
|
removeRole(role: Role) {
|
||||||
|
self.roles.remove(role);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
get allTasks() {
|
||||||
|
return self.roles.flatMap(r => r.allTasks);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Field extends Instance<typeof FieldModel> {}
|
||||||
|
|
||||||
|
/* Profession ------------------------------------------------------------ */
|
||||||
|
export const ProfessionModel = withId("Profession", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.maybe(types.string),
|
||||||
|
fields: types.optional(types.array(FieldModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addField(field: SnapshotIn<typeof FieldModel>) {
|
||||||
|
self.fields.push(FieldModel.create(field));
|
||||||
|
},
|
||||||
|
removeField(field: Field) {
|
||||||
|
self.fields.remove(field);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
get allTasks() {
|
||||||
|
return self.fields.flatMap(f => f.allTasks);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Profession extends Instance<typeof ProfessionModel> {}
|
||||||
|
|
||||||
|
/* Industry -------------------------------------------------------------- */
|
||||||
|
export const IndustryModel = withId("Industry", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.maybe(types.string),
|
||||||
|
professions: types.optional(types.array(ProfessionModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addProfession(prof: SnapshotIn<typeof ProfessionModel>) {
|
||||||
|
self.professions.push(ProfessionModel.create(prof));
|
||||||
|
},
|
||||||
|
removeProfession(prof: Profession) {
|
||||||
|
self.professions.remove(prof);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
get allTasks() {
|
||||||
|
return self.professions.flatMap(p => p.allTasks);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Industry extends Instance<typeof IndustryModel> {}
|
||||||
|
|
||||||
|
/* Domain ---------------------------------------------------------------- */
|
||||||
|
export const DomainModel = withId("Domain", {
|
||||||
|
name: types.string,
|
||||||
|
description: types.maybe(types.string),
|
||||||
|
industries: types.optional(types.array(IndustryModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addIndustry(ind: SnapshotIn<typeof IndustryModel>) {
|
||||||
|
self.industries.push(IndustryModel.create(ind));
|
||||||
|
},
|
||||||
|
removeIndustry(ind: Industry) {
|
||||||
|
self.industries.remove(ind);
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
destroy(self);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
get allTasks() {
|
||||||
|
return self.industries.flatMap(i => i.allTasks);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface Domain extends Instance<typeof DomainModel> {}
|
||||||
|
|
||||||
|
/* Enterprise ------------------------------------------------------------- */
|
||||||
|
export const Enterprise = types
|
||||||
|
.model("Enterprise", {
|
||||||
|
domains: types.optional(types.array(DomainModel), [])
|
||||||
|
})
|
||||||
|
.actions(self => ({
|
||||||
|
addDomain(domain: SnapshotIn<typeof DomainModel>) {
|
||||||
|
self.domains.push(DomainModel.create(domain));
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.views(self => ({
|
||||||
|
// Convenience: get a flat list of everything
|
||||||
|
get allTasks() {
|
||||||
|
return self.domains.flatMap(d => d.allTasks);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
export interface IRootStore extends Instance<typeof Enterprise> {}
|
||||||
|
|
||||||
|
/* Example usage --------------------------------------------------------- */
|
||||||
|
// const store = Enterprise.create({});
|
||||||
|
// store.addDomain({ name: "STEM" });
|
||||||
|
// store.domains[0].addIndustry({ name: "Software" });
|
||||||
|
// store.domains[0].industries[0].addProfession({ name: "Software Engineering" });
|
||||||
|
// store.domains[0].industries[0].professions[0].addField({ name: "Backend" });
|
||||||
|
// store.domains[0].industries[0].professions[0].fields[0].addRole({ title: "API Engineer" });
|
||||||
|
// store.domains[0].industries[0].professions[0].fields[0].roles[0].addTask({ name: "Design REST endpoints" });
|
||||||
|
// console.log(store.allTasks.map(t => t.name)); // → ["Design REST endpoints"]
|
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"domain": "Finance",
|
||||||
|
"structure": [
|
||||||
|
"Retail Banking",
|
||||||
|
"Commercial Banking",
|
||||||
|
"Investment Banking",
|
||||||
|
"Private Banking"
|
||||||
|
],
|
||||||
|
"description": "A hierarchy of functions and services within the banking sector, focusing on various banking operations.",
|
||||||
|
"commonSkills": [
|
||||||
|
"Financial Analysis",
|
||||||
|
"Risk Management",
|
||||||
|
"Customer Relationship Management",
|
||||||
|
"Regulatory Compliance",
|
||||||
|
"Loan Processing"
|
||||||
|
],
|
||||||
|
"commonTools": [
|
||||||
|
"Financial Modeling Software",
|
||||||
|
"Customer Relationship Management (CRM) Systems",
|
||||||
|
"Investment Analysis Tools",
|
||||||
|
"Risk Assessment Software"
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"Personal loans in Retail Banking",
|
||||||
|
"Small business loans in Commercial Banking",
|
||||||
|
"Mergers and Acquisitions in Investment Banking",
|
||||||
|
"Wealth management in Private Banking"
|
||||||
|
]
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* finance Professional Hierarchy Example
|
||||||
|
* Generated using OpenAI Agents SDK and Sumpin Professional Hierarchy Models
|
||||||
|
* Model Version: v2 (6-layer hierarchy)
|
||||||
|
* Generated on: 2025-07-11T20:02:03.514Z
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Enterprise,
|
||||||
|
DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel
|
||||||
|
} from "../../lib/v2";
|
||||||
|
|
||||||
|
import { Enterprise, DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel } from "../../lib/v2";
|
||||||
|
|
||||||
|
const financeDomain = new DomainModel({
|
||||||
|
name: "Finance",
|
||||||
|
industries: [
|
||||||
|
new IndustryModel({
|
||||||
|
name: "Investment Banking",
|
||||||
|
professions: [
|
||||||
|
new ProfessionModel({
|
||||||
|
name: "Investment Banker",
|
||||||
|
fields: [
|
||||||
|
new FieldModel({
|
||||||
|
name: "Corporate Finance",
|
||||||
|
roles: [
|
||||||
|
new RoleModel({
|
||||||
|
name: "Analyst",
|
||||||
|
tasks: [
|
||||||
|
new TaskModel({
|
||||||
|
name: "Financial Modeling",
|
||||||
|
skills: ["Excel", "Financial Analysis"],
|
||||||
|
tools: ["Excel", "Bloomberg Terminal"],
|
||||||
|
example: "Building a discounted cash flow model for a merger."
|
||||||
|
}),
|
||||||
|
new TaskModel({
|
||||||
|
name: "Market Research",
|
||||||
|
skills: ["Data Analysis", "Presentation Skills"],
|
||||||
|
tools: ["PitchBook", "Excel"],
|
||||||
|
example: "Analyzing competitor performance for a potential acquisition."
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new RoleModel({
|
||||||
|
name: "Associate",
|
||||||
|
tasks: [
|
||||||
|
new TaskModel({
|
||||||
|
name: "Deal Execution",
|
||||||
|
skills: ["Negotiation", "Project Management"],
|
||||||
|
tools: ["MS Project", "Deal Management Software"],
|
||||||
|
example: "Leading a team to close a multi-million dollar equity issuance."
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Basic operations
|
||||||
|
const readRoleTasks = (roleName: string) => {
|
||||||
|
const role = financeDomain.industries[0].professions[0].fields[0].roles.find(r => r.name === roleName);
|
||||||
|
return role ? role.tasks : [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateTaskSkill = (roleName: string, taskName: string, newSkills: string[]) => {
|
||||||
|
const role = financeDomain.industries[0].professions[0].fields[0].roles.find(r => r.name === roleName);
|
||||||
|
const task = role?.tasks.find(t => t.name === taskName);
|
||||||
|
if (task) {
|
||||||
|
task.skills = newSkills;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Example usages
|
||||||
|
const analystTasks = readRoleTasks("Analyst");
|
||||||
|
updateTaskSkill("Analyst", "Financial Modeling", ["Advanced Excel", "Financial Forecasting"]);
|
@@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
* healthcare Professional Hierarchy Example
|
||||||
|
* Generated using OpenAI Agents SDK and Sumpin Professional Hierarchy Models
|
||||||
|
* Model Version: v2 (6-layer hierarchy)
|
||||||
|
* Generated on: 2025-07-11T20:01:29.107Z
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Enterprise,
|
||||||
|
DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel
|
||||||
|
} from "../../lib/v2";
|
||||||
|
|
||||||
|
import { Enterprise, DomainModel, IndustryModel, ProfessionModel, FieldModel, RoleModel, TaskModel } from "../../lib/v2";
|
||||||
|
const healthcareDomain = new DomainModel({
|
||||||
|
name: "Healthcare",
|
||||||
|
industries: [
|
||||||
|
new IndustryModel({
|
||||||
|
name: "Medical Services",
|
||||||
|
professions: [
|
||||||
|
new ProfessionModel({
|
||||||
|
name: "Nursing",
|
||||||
|
fields: [
|
||||||
|
new FieldModel({
|
||||||
|
name: "Clinical Nursing",
|
||||||
|
roles: [
|
||||||
|
new RoleModel({
|
||||||
|
name: "Registered Nurse",
|
||||||
|
competencies: [
|
||||||
|
"Patient assessment",
|
||||||
|
"Medication administration",
|
||||||
|
"Care planning"
|
||||||
|
],
|
||||||
|
tools: [
|
||||||
|
"Electronic Health Records (EHR)",
|
||||||
|
"Vital signs monitors",
|
||||||
|
"Infusion pumps"
|
||||||
|
],
|
||||||
|
tasks: [
|
||||||
|
new TaskModel({
|
||||||
|
name: "Patient Monitoring",
|
||||||
|
description: "Monitoring patient vitals and documenting changes.",
|
||||||
|
examples: [
|
||||||
|
"Using EHR to log vital signs every hour.",
|
||||||
|
"Adjusting care plan based on patient observations."
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new TaskModel({
|
||||||
|
name: "Medication Management",
|
||||||
|
description: "Administering and managing patient medications.",
|
||||||
|
examples: [
|
||||||
|
"Preparing and administering IV medications.",
|
||||||
|
"Educating patients on prescribed medications."
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new FieldModel({
|
||||||
|
name: "Nurse Practitioner",
|
||||||
|
roles: [
|
||||||
|
new RoleModel({
|
||||||
|
name: "Family Nurse Practitioner",
|
||||||
|
competencies: [
|
||||||
|
"Advanced patient assessment",
|
||||||
|
"Diagnosis and treatment planning",
|
||||||
|
"Patient education"
|
||||||
|
],
|
||||||
|
tools: [
|
||||||
|
"Diagnostic tools (stethoscope, otoscope)",
|
||||||
|
"Telehealth platform",
|
||||||
|
"Prescription software"
|
||||||
|
],
|
||||||
|
tasks: [
|
||||||
|
new TaskModel({
|
||||||
|
name: "Conducting Physical Exams",
|
||||||
|
description: "Performing comprehensive assessments for patients.",
|
||||||
|
examples: [
|
||||||
|
"Utilizing telehealth for remote consultations.",
|
||||||
|
"Documenting findings and recommending treatments."
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new TaskModel({
|
||||||
|
name: "Health Promotion",
|
||||||
|
description: "Educating families about preventive care.",
|
||||||
|
examples: [
|
||||||
|
"Organizing community health seminars.",
|
||||||
|
"Providing personalized health advice to families."
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new ProfessionModel({
|
||||||
|
name: "Healthcare Administration",
|
||||||
|
fields: [
|
||||||
|
new FieldModel({
|
||||||
|
name: "Hospital Administration",
|
||||||
|
roles: [
|
||||||
|
new RoleModel({
|
||||||
|
name: "Healthcare Administrator",
|
||||||
|
competencies: [
|
||||||
|
"Operations management",
|
||||||
|
"Compliance and regulations",
|
||||||
|
"Financial planning"
|
||||||
|
],
|
||||||
|
tools: [
|
||||||
|
"Healthcare management software",
|
||||||
|
"Data analytics tools",
|
||||||
|
"Budgeting tools"
|
||||||
|
],
|
||||||
|
tasks: [
|
||||||
|
new TaskModel({
|
||||||
|
name: "Budgeting and Financial Oversight",
|
||||||
|
description: "Managing hospital budgets and financial resources.",
|
||||||
|
examples: [
|
||||||
|
"Creating annual budgets based on service demand.",
|
||||||
|
"Reviewing financial performance reports."
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new TaskModel({
|
||||||
|
name: "Quality Improvement Initiatives",
|
||||||
|
description: "Implementing strategies to improve healthcare delivery.",
|
||||||
|
examples: [
|
||||||
|
"Conducting patient satisfaction surveys.",
|
||||||
|
"Analyzing workflow for efficiency."
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
export default healthcareDomain;
|
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"domain": "Technology",
|
||||||
|
"structure": [
|
||||||
|
"Front-end",
|
||||||
|
"Back-end",
|
||||||
|
"Database",
|
||||||
|
"DevOps"
|
||||||
|
],
|
||||||
|
"description": "A hierarchy outlining the main components and roles involved in web development.",
|
||||||
|
"commonSkills": [
|
||||||
|
"HTML/CSS",
|
||||||
|
"JavaScript",
|
||||||
|
"Responsive Design",
|
||||||
|
"Backend Programming",
|
||||||
|
"Database Management"
|
||||||
|
],
|
||||||
|
"commonTools": [
|
||||||
|
"Visual Studio Code",
|
||||||
|
"Git",
|
||||||
|
"Postman",
|
||||||
|
"Node.js",
|
||||||
|
"MySQL"
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"Building a static website",
|
||||||
|
"Creating a dynamic web application",
|
||||||
|
"Developing APIs",
|
||||||
|
"Implementing user authentication"
|
||||||
|
]
|
||||||
|
}
|
27
package.json
Normal file
27
package.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "sumpin",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/uuid": "^10.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "bun ./index.ts",
|
||||||
|
"cli": "bun ./cli.ts",
|
||||||
|
"sumpin": "bun ./cli.ts",
|
||||||
|
"generate": "bun ./cli.ts",
|
||||||
|
"demo": "bun ./index.ts"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@openai/agents": "^0.0.11",
|
||||||
|
"mobx": "^6.13.7",
|
||||||
|
"mobx-state-tree": "^7.0.2",
|
||||||
|
"openai": "^5.9.0",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
|
"zod": "<=3.25.67"
|
||||||
|
}
|
||||||
|
}
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
32
tsconfig.json
Normal file
32
tsconfig.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable latest features
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"*.ts",
|
||||||
|
"lib/**/*",
|
||||||
|
"examples/**/*"
|
||||||
|
]
|
||||||
|
}
|
Reference in New Issue
Block a user