@tpmjs/official-policy-doc-format 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 TPMJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,61 @@
1
+ import * as ai from 'ai';
2
+
3
+ /**
4
+ * Policy Document Format Tool for TPMJS
5
+ * Formats HR policy content into standardized policy document structure
6
+ */
7
+ /**
8
+ * Policy metadata
9
+ */
10
+ interface PolicyMetadata {
11
+ title?: string;
12
+ policyNumber?: string;
13
+ owner?: string;
14
+ department?: string;
15
+ effectiveDate?: string;
16
+ reviewDate?: string;
17
+ version?: string;
18
+ approvedBy?: string;
19
+ }
20
+ /**
21
+ * Input interface for policy document formatting
22
+ */
23
+ interface PolicyDocFormatInput {
24
+ policyContent: string;
25
+ metadata?: PolicyMetadata;
26
+ }
27
+ /**
28
+ * Formatted policy document structure
29
+ */
30
+ interface PolicyDocument {
31
+ header: {
32
+ title: string;
33
+ policyNumber?: string;
34
+ version: string;
35
+ effectiveDate: string;
36
+ reviewDate: string;
37
+ owner: string;
38
+ approvedBy?: string;
39
+ };
40
+ purpose: string;
41
+ scope: string;
42
+ policyStatement: string;
43
+ procedures: string[];
44
+ responsibilities: Record<string, string[]>;
45
+ definitions?: Record<string, string>;
46
+ relatedPolicies?: string[];
47
+ enforcement?: string;
48
+ revisionHistory?: Array<{
49
+ version: string;
50
+ date: string;
51
+ changes: string;
52
+ }>;
53
+ fullDocument: string;
54
+ }
55
+ /**
56
+ * Policy Document Format Tool
57
+ * Formats HR policy content into standardized policy document structure
58
+ */
59
+ declare const policyDocFormatTool: ai.Tool<PolicyDocFormatInput, PolicyDocument>;
60
+
61
+ export { type PolicyDocument, policyDocFormatTool as default, policyDocFormatTool };
package/dist/index.js ADDED
@@ -0,0 +1,296 @@
1
+ import { tool, jsonSchema } from 'ai';
2
+
3
+ // src/index.ts
4
+ var policyDocFormatTool = tool({
5
+ description: "Formats HR policy content into a standardized policy document structure. Creates organized sections including purpose, scope, policy statement, procedures, responsibilities, and metadata with effective date, owner, and review date.",
6
+ inputSchema: jsonSchema({
7
+ type: "object",
8
+ properties: {
9
+ policyContent: {
10
+ type: "string",
11
+ description: "Raw policy content to be formatted into standard structure",
12
+ minLength: 10
13
+ },
14
+ metadata: {
15
+ type: "object",
16
+ properties: {
17
+ title: { type: "string", description: "Policy title" },
18
+ policyNumber: { type: "string", description: "Policy number or identifier" },
19
+ owner: { type: "string", description: "Policy owner (name or department)" },
20
+ department: { type: "string", description: "Responsible department" },
21
+ effectiveDate: { type: "string", description: "Policy effective date" },
22
+ reviewDate: { type: "string", description: "Next review date" },
23
+ version: { type: "string", description: "Policy version" },
24
+ approvedBy: { type: "string", description: "Approver name or title" }
25
+ },
26
+ description: "Policy metadata and administrative information"
27
+ }
28
+ },
29
+ required: ["policyContent"],
30
+ additionalProperties: false
31
+ }),
32
+ execute: async ({ policyContent, metadata = {} }) => {
33
+ if (!policyContent || typeof policyContent !== "string" || policyContent.trim().length < 10) {
34
+ throw new Error("Policy content must be a non-empty string with at least 10 characters");
35
+ }
36
+ try {
37
+ const title = metadata.title || extractTitle(policyContent) || "Human Resources Policy";
38
+ const today = /* @__PURE__ */ new Date();
39
+ const effectiveDate = metadata.effectiveDate || today.toLocaleDateString("en-US", {
40
+ year: "numeric",
41
+ month: "long",
42
+ day: "numeric"
43
+ });
44
+ const nextYear = new Date(today);
45
+ nextYear.setFullYear(today.getFullYear() + 1);
46
+ const reviewDate = metadata.reviewDate || nextYear.toLocaleDateString("en-US", {
47
+ year: "numeric",
48
+ month: "long",
49
+ day: "numeric"
50
+ });
51
+ const header = {
52
+ title,
53
+ policyNumber: metadata.policyNumber,
54
+ version: metadata.version || "1.0",
55
+ effectiveDate,
56
+ reviewDate,
57
+ owner: metadata.owner || metadata.department || "Human Resources",
58
+ approvedBy: metadata.approvedBy
59
+ };
60
+ const purpose = extractPurpose(policyContent);
61
+ const scope = extractScope(policyContent);
62
+ const policyStatement = extractPolicyStatement(policyContent);
63
+ const procedures = extractProcedures(policyContent);
64
+ const responsibilities = extractResponsibilities(policyContent);
65
+ const definitions = extractDefinitions(policyContent);
66
+ const relatedPolicies = extractRelatedPolicies(policyContent);
67
+ const enforcement = extractEnforcement(policyContent);
68
+ const fullDocument = buildFullDocument(
69
+ header,
70
+ purpose,
71
+ scope,
72
+ policyStatement,
73
+ procedures,
74
+ responsibilities,
75
+ definitions,
76
+ relatedPolicies,
77
+ enforcement
78
+ );
79
+ return {
80
+ header,
81
+ purpose,
82
+ scope,
83
+ policyStatement,
84
+ procedures,
85
+ responsibilities,
86
+ definitions: definitions.size > 0 ? Object.fromEntries(definitions) : void 0,
87
+ relatedPolicies: relatedPolicies.length > 0 ? relatedPolicies : void 0,
88
+ enforcement,
89
+ revisionHistory: [
90
+ {
91
+ version: header.version,
92
+ date: effectiveDate,
93
+ changes: "Initial version"
94
+ }
95
+ ],
96
+ fullDocument
97
+ };
98
+ } catch (error) {
99
+ throw new Error(
100
+ `Failed to format policy document: ${error instanceof Error ? error.message : String(error)}`
101
+ );
102
+ }
103
+ }
104
+ });
105
+ function extractTitle(content) {
106
+ const lines = content.split("\n").filter((l) => l.trim());
107
+ if (lines.length > 0 && lines[0]) {
108
+ const firstLine = lines[0].trim();
109
+ if (firstLine.length < 100 && !firstLine.includes(".")) {
110
+ return firstLine.replace(/^#+\s*/, "");
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ function extractPurpose(content) {
116
+ const purposeMatch = content.match(
117
+ /(?:purpose|objective|intent)[\s:]+(.+?)(?=\n\n|scope|policy|$)/is
118
+ );
119
+ if (purposeMatch && purposeMatch[1]) {
120
+ return purposeMatch[1].trim();
121
+ }
122
+ return "This policy establishes guidelines and procedures to ensure consistency, compliance, and best practices within the organization.";
123
+ }
124
+ function extractScope(content) {
125
+ const scopeMatch = content.match(/scope[\s:]+(.+?)(?=\n\n|policy|procedure|$)/is);
126
+ if (scopeMatch && scopeMatch[1]) {
127
+ return scopeMatch[1].trim();
128
+ }
129
+ return "This policy applies to all employees, contractors, and other personnel associated with the organization.";
130
+ }
131
+ function extractPolicyStatement(content) {
132
+ const statementMatch = content.match(/policy[\s:]+(.+?)(?=\n\n|procedure|$)/is);
133
+ if (statementMatch && statementMatch[1]) {
134
+ return statementMatch[1].trim();
135
+ }
136
+ const paragraphs = content.split("\n\n").filter((p) => p.trim().length > 50);
137
+ return paragraphs[0] || content.substring(0, 500);
138
+ }
139
+ function extractProcedures(content) {
140
+ const procedures = [];
141
+ const procedureSection = content.match(/procedure[s]?[\s:]+(.+?)(?=\n\n[A-Z]|$)/is);
142
+ if (procedureSection && procedureSection[1]) {
143
+ const text = procedureSection[1];
144
+ const matches = text.match(/(?:^|\n)\s*(?:\d+\.|[-*])\s*(.+)/gm);
145
+ if (matches) {
146
+ procedures.push(...matches.map((m) => m.replace(/^\s*(?:\d+\.|[-*])\s*/, "").trim()));
147
+ }
148
+ }
149
+ if (procedures.length === 0) {
150
+ procedures.push(
151
+ "Review and understand this policy",
152
+ "Follow established guidelines and procedures",
153
+ "Report violations or concerns to management",
154
+ "Participate in required training"
155
+ );
156
+ }
157
+ return procedures;
158
+ }
159
+ function extractResponsibilities(content) {
160
+ const responsibilities = {};
161
+ const respMatch = content.match(/responsibilit(?:ies|y)[\s:]+(.+?)(?=\n\n[A-Z]|$)/is);
162
+ if (respMatch && respMatch[1]) {
163
+ const text = respMatch[1];
164
+ const roleMatches = text.matchAll(/([A-Za-z\s]+?)[:]\s*(.+?)(?=\n[A-Z]|$)/gs);
165
+ for (const match of roleMatches) {
166
+ const role = match[1]?.trim();
167
+ const dutiesText = match[2];
168
+ if (role && dutiesText) {
169
+ const duties = dutiesText.split(/[;,]|(?:\n\s*[-*])/g).map((d) => d.trim()).filter((d) => d.length > 0);
170
+ responsibilities[role] = duties;
171
+ }
172
+ }
173
+ }
174
+ if (Object.keys(responsibilities).length === 0) {
175
+ responsibilities["Employees"] = [
176
+ "Comply with policy requirements",
177
+ "Report violations or concerns"
178
+ ];
179
+ responsibilities["Managers"] = [
180
+ "Ensure team compliance",
181
+ "Address policy violations",
182
+ "Provide guidance and support"
183
+ ];
184
+ responsibilities["HR Department"] = [
185
+ "Maintain and update policy",
186
+ "Provide training and resources",
187
+ "Monitor compliance"
188
+ ];
189
+ }
190
+ return responsibilities;
191
+ }
192
+ function extractDefinitions(content) {
193
+ const definitions = /* @__PURE__ */ new Map();
194
+ const defMatch = content.match(/definition[s]?[\s:]+(.+?)(?=\n\n[A-Z]|$)/is);
195
+ if (defMatch && defMatch[1]) {
196
+ const text = defMatch[1];
197
+ const termMatches = text.matchAll(/([A-Za-z\s]+?)[:]\s*(.+?)(?=\n|$)/g);
198
+ for (const match of termMatches) {
199
+ const term = match[1]?.trim();
200
+ const definition = match[2]?.trim();
201
+ if (term && definition) {
202
+ definitions.set(term, definition);
203
+ }
204
+ }
205
+ }
206
+ return definitions;
207
+ }
208
+ function extractRelatedPolicies(content) {
209
+ const policies = [];
210
+ const relatedMatch = content.match(/related\s+polic(?:ies|y)[\s:]+(.+?)(?=\n\n|$)/is);
211
+ if (relatedMatch && relatedMatch[1]) {
212
+ const text = relatedMatch[1];
213
+ const policyMatches = text.match(/(?:^|\n)\s*(?:\d+\.|[-*])\s*(.+)/gm);
214
+ if (policyMatches) {
215
+ policies.push(...policyMatches.map((m) => m.replace(/^\s*(?:\d+\.|[-*])\s*/, "").trim()));
216
+ }
217
+ }
218
+ return policies;
219
+ }
220
+ function extractEnforcement(content) {
221
+ const enforcementMatch = content.match(/enforcement|violation[s]?[\s:]+(.+?)(?=\n\n|$)/is);
222
+ if (enforcementMatch && enforcementMatch[1]) {
223
+ return enforcementMatch[1].trim();
224
+ }
225
+ return "Violations of this policy may result in disciplinary action up to and including termination of employment. The severity of disciplinary action will depend on the nature and circumstances of the violation.";
226
+ }
227
+ function buildFullDocument(header, purpose, scope, policyStatement, procedures, responsibilities, definitions, relatedPolicies, enforcement) {
228
+ const sections = [];
229
+ sections.push("\u2550".repeat(80));
230
+ sections.push(header.title.toUpperCase());
231
+ sections.push("\u2550".repeat(80));
232
+ sections.push("");
233
+ if (header.policyNumber) sections.push(`Policy Number: ${header.policyNumber}`);
234
+ sections.push(`Version: ${header.version}`);
235
+ sections.push(`Effective Date: ${header.effectiveDate}`);
236
+ sections.push(`Review Date: ${header.reviewDate}`);
237
+ sections.push(`Owner: ${header.owner}`);
238
+ if (header.approvedBy) sections.push(`Approved By: ${header.approvedBy}`);
239
+ sections.push("");
240
+ sections.push("1. PURPOSE");
241
+ sections.push("\u2500".repeat(80));
242
+ sections.push(purpose);
243
+ sections.push("");
244
+ sections.push("2. SCOPE");
245
+ sections.push("\u2500".repeat(80));
246
+ sections.push(scope);
247
+ sections.push("");
248
+ sections.push("3. POLICY STATEMENT");
249
+ sections.push("\u2500".repeat(80));
250
+ sections.push(policyStatement);
251
+ sections.push("");
252
+ sections.push("4. PROCEDURES");
253
+ sections.push("\u2500".repeat(80));
254
+ procedures.forEach((proc, idx) => {
255
+ sections.push(`${idx + 1}. ${proc}`);
256
+ });
257
+ sections.push("");
258
+ sections.push("5. RESPONSIBILITIES");
259
+ sections.push("\u2500".repeat(80));
260
+ for (const [role, duties] of Object.entries(responsibilities)) {
261
+ sections.push(`${role}:`);
262
+ duties.forEach((duty) => {
263
+ sections.push(` \u2022 ${duty}`);
264
+ });
265
+ sections.push("");
266
+ }
267
+ if (definitions && definitions.size > 0) {
268
+ sections.push("6. DEFINITIONS");
269
+ sections.push("\u2500".repeat(80));
270
+ for (const [term, definition] of definitions) {
271
+ sections.push(`${term}: ${definition}`);
272
+ }
273
+ sections.push("");
274
+ }
275
+ if (relatedPolicies && relatedPolicies.length > 0) {
276
+ sections.push("7. RELATED POLICIES");
277
+ sections.push("\u2500".repeat(80));
278
+ relatedPolicies.forEach((policy) => {
279
+ sections.push(`\u2022 ${policy}`);
280
+ });
281
+ sections.push("");
282
+ }
283
+ if (enforcement) {
284
+ sections.push("8. ENFORCEMENT");
285
+ sections.push("\u2500".repeat(80));
286
+ sections.push(enforcement);
287
+ sections.push("");
288
+ }
289
+ sections.push("\u2550".repeat(80));
290
+ sections.push("END OF POLICY DOCUMENT");
291
+ sections.push("\u2550".repeat(80));
292
+ return sections.join("\n");
293
+ }
294
+ var index_default = policyDocFormatTool;
295
+
296
+ export { index_default as default, policyDocFormatTool };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@tpmjs/official-policy-doc-format",
3
+ "version": "0.1.0",
4
+ "description": "Formats HR policy content into standardized policy document structure",
5
+ "type": "module",
6
+ "keywords": [
7
+ "tpmjs",
8
+ "hr",
9
+ "policy",
10
+ "documentation",
11
+ "compliance"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "devDependencies": {
23
+ "tsup": "^8.3.5",
24
+ "typescript": "^5.9.3",
25
+ "@tpmjs/tsconfig": "0.0.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/anthropics/tpmjs.git",
33
+ "directory": "packages/tools/official/policy-doc-format"
34
+ },
35
+ "homepage": "https://tpmjs.com",
36
+ "license": "MIT",
37
+ "tpmjs": {
38
+ "category": "hr",
39
+ "frameworks": [
40
+ "vercel-ai"
41
+ ],
42
+ "tools": [
43
+ {
44
+ "name": "policyDocFormatTool",
45
+ "description": "Formats HR policy content into standardized policy document structure",
46
+ "parameters": [
47
+ {
48
+ "name": "policyContent",
49
+ "type": "string",
50
+ "description": "Raw policy content to format",
51
+ "required": true
52
+ },
53
+ {
54
+ "name": "metadata",
55
+ "type": "object",
56
+ "description": "Policy metadata (title, owner, dates)",
57
+ "required": false
58
+ }
59
+ ],
60
+ "returns": {
61
+ "type": "PolicyDocument",
62
+ "description": "Formatted policy document with standard structure"
63
+ }
64
+ }
65
+ ]
66
+ },
67
+ "dependencies": {
68
+ "ai": "6.0.0-beta.124"
69
+ },
70
+ "scripts": {
71
+ "build": "tsup",
72
+ "dev": "tsup --watch",
73
+ "type-check": "tsc --noEmit",
74
+ "clean": "rm -rf dist .turbo"
75
+ }
76
+ }