@drdoc-com/pi-drdoc 1.0.2 → 1.0.4
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/README.md +17 -1
- package/package.json +5 -5
- package/src/drdoc-client.ts +16 -7
- package/src/index.ts +4 -4
- package/src/tools.ts +23 -7
package/README.md
CHANGED
|
@@ -60,11 +60,18 @@ Example:
|
|
|
60
60
|
/drdoc_login https://drdoc.com demo password "" 1
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
And signout/
|
|
63
|
+
And signout/logout:
|
|
64
64
|
```bash
|
|
65
65
|
/drdoc_logout
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
### Pi Agent Tool Calling
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
```
|
|
72
|
+
Suche im Dr.DOC Archiv "rec" alle Rechnungen von Firma Amazon aus diesem Jahr.
|
|
73
|
+
```
|
|
74
|
+
|
|
68
75
|
## Configuration
|
|
69
76
|
|
|
70
77
|
The plugin utilizes configuration options supplied by the Dr.DOC client or environment variables.
|
|
@@ -77,10 +84,19 @@ The plugin utilizes configuration options supplied by the Dr.DOC client or envir
|
|
|
77
84
|
| `DRDOC_CONFIG_DIR` (alt. `PI_CONFIG_DIR`) | Custom directory for config files | `~/.pi/agent` |
|
|
78
85
|
| `DRDOC_DOWNLOAD_DIR` | Custom directory for downloaded files | `~/.drdoc/downloads` |
|
|
79
86
|
| `DRDOC_IGNORE_SSL` | Ignore TLS/SSL Errors (Set `NODE_TLS_REJECT_UNAUTHORIZED=0`) | `` |
|
|
87
|
+
| `DRDOC_AI_FS` | Dr.DOC IMPORT_ASCII FieldSelection Name for Field Descriptions. | `STD_AI_INVOICE_IN`, `DD_FIELD_DESC`, `STD_FIELD_DESC` |
|
|
80
88
|
| `DRDOC_DEBUG` | Enable Debugging | `` |
|
|
81
89
|
|
|
82
90
|
---
|
|
83
91
|
|
|
92
|
+
### Security Notes
|
|
93
|
+
* Pi Agent is designed as a **personal** AI agent. Users must operate their own private Pi Agent instance rather than using an instance hosted on the Dr.DOC Web Server.
|
|
94
|
+
* Credential Persistence (/drdoc_login): When using the Dr.DOC AI Chat with Pi configured as the AI endpoint (via `@drdoc-com/pi-openai-api-wrapper`), the `/drdoc_login` command *MUST NOT* be executed. Authentication credentials within the Pi Agent instance are persistent and could potentially be exposed to other users sharing the same instance.
|
|
95
|
+
* Dedicated Service Account: Use a dedicated Dr.DOC user account with limited permissions (e.g. *Datensatzspezifische Berechtigungen*) based on the principle of least privilege (*"need-to-know"*) specifically for AI tasks and the `/drdoc_login` command.
|
|
96
|
+
* Containerized Deployment: Whenever possible, run Pi Agent inside an isolated container environment (e.g., Docker, Podman) to ensure process isolation and security boundaries.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
84
100
|
## License
|
|
85
101
|
|
|
86
102
|
This project is licensed under the Apache License 2.0.
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drdoc-com/pi-drdoc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Dr.DOC DMS Integration Package for PI Agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache License 2.0",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"pi-package",
|
|
9
9
|
"pi-agent",
|
|
10
|
-
"drdoc",
|
|
11
10
|
"rest-api",
|
|
12
11
|
"skill",
|
|
13
|
-
"
|
|
14
|
-
"Dr.DOC"
|
|
12
|
+
"drdoc",
|
|
13
|
+
"Dr.DOC",
|
|
14
|
+
"dms"
|
|
15
15
|
],
|
|
16
16
|
"private": false,
|
|
17
17
|
"pi": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"author": "Dr.DOC GmbH, DE-80802 Munich",
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "^7.0.2",
|
|
34
|
-
"@types/node": "^
|
|
34
|
+
"@types/node": "^24.0.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@earendil-works/pi-coding-agent": "*"
|
package/src/drdoc-client.ts
CHANGED
|
@@ -163,7 +163,8 @@ export class DrDocClient {
|
|
|
163
163
|
try {
|
|
164
164
|
const dataToSave = JSON.stringify(this.config, null, 2);
|
|
165
165
|
fs.writeFileSync(this.storageFilePath, dataToSave, "utf-8");
|
|
166
|
-
|
|
166
|
+
if (process.env.DRDOC_DEBUG)
|
|
167
|
+
msgLog('Dr.DOC Anmeldedaten wurden gespeichert unter: ', this.storageFilePath);
|
|
167
168
|
} catch (error) {
|
|
168
169
|
throw new Error(`Fehler beim Speichern der Anmeldedaten: ${error instanceof Error ? error.message : String(error)}`);
|
|
169
170
|
}
|
|
@@ -192,8 +193,11 @@ export class DrDocClient {
|
|
|
192
193
|
if (setCookie) {
|
|
193
194
|
const match = setCookie.match(/uid=([^;]+)/);
|
|
194
195
|
if (match) {
|
|
196
|
+
const oldCookieValue = this.config.sessionCookie;
|
|
195
197
|
this.config.sessionCookie = `uid=${match[1]}`;
|
|
196
|
-
//
|
|
198
|
+
// bei Cookie Änderung, Cookie uid explizit abspeichern
|
|
199
|
+
if (oldCookieValue != this.config.sessionCookie)
|
|
200
|
+
this.saveCredentials();
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
203
|
}
|
|
@@ -330,11 +334,13 @@ export class DrDocClient {
|
|
|
330
334
|
// Dauerhaftes Speichern der gesamten DrDocConfig nach erfolgreichem Login
|
|
331
335
|
this.saveCredentials();
|
|
332
336
|
|
|
333
|
-
|
|
337
|
+
if (process.env.DRDOC_DEBUG)
|
|
338
|
+
msgLog('DD: Sign in OK: ', JSON.stringify(this.config));
|
|
334
339
|
}
|
|
335
340
|
else {
|
|
336
|
-
|
|
337
|
-
|
|
341
|
+
//if (process.env.DRDOC_DEBUG)
|
|
342
|
+
if (process.env.DRDOC_DEBUG)
|
|
343
|
+
msgLog('DD: Sign in ERROR: ' + JSON.stringify(this.config));
|
|
338
344
|
}
|
|
339
345
|
|
|
340
346
|
return response;
|
|
@@ -349,11 +355,14 @@ export class DrDocClient {
|
|
|
349
355
|
|
|
350
356
|
// Überprüfung auf erfolgreiche Anmeldung
|
|
351
357
|
if (response && !response.HasError) {
|
|
352
|
-
|
|
358
|
+
if (process.env.DRDOC_DEBUG)
|
|
359
|
+
msgLog('Dr.DOC: State OK:', this.config);
|
|
353
360
|
return true;
|
|
354
361
|
}
|
|
355
362
|
else {
|
|
356
|
-
msgError('
|
|
363
|
+
msgError('Bitte erneut anmelden mit Slash Command `/drdoc_login`');
|
|
364
|
+
if (process.env.DRDOC_DEBUG)
|
|
365
|
+
msgLog('Dr.DOC: State ERROR: ' + JSON.stringify(this.config));
|
|
357
366
|
return false;
|
|
358
367
|
}
|
|
359
368
|
}
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ export default function (pi: any): void {
|
|
|
17
17
|
|
|
18
18
|
// Login
|
|
19
19
|
pi.registerCommand("drdoc_login", {
|
|
20
|
-
description: "Benutzer anmelden in Dr.DOC über die REST API und speichert die Session
|
|
20
|
+
description: "Benutzer anmelden in Dr.DOC über die REST API und speichert die Session: `/drdoc_login <baseUrl> <username> <password> <totp> <ignoreSSL:1,0>`",
|
|
21
21
|
handler: async (args: string, ctx: any) => {
|
|
22
22
|
// Entfernen leerer Strings nach dem String-Split
|
|
23
23
|
const parts = args.trim().split(/\s+/); //.filter(Boolean);
|
|
@@ -34,18 +34,18 @@ export default function (pi: any): void {
|
|
|
34
34
|
try {
|
|
35
35
|
//initializeDrDocClient({ baseUrl, username, password, totp, ignoreSSL });
|
|
36
36
|
//const client = new DrDocClient({ baseUrl, username, password, totp, ignoreSSL });
|
|
37
|
-
const client = await getClient({ baseUrl, username, password, totp, ignoreSSL: (ignoreSSL == '1' || ignoreSSL == 'true') });
|
|
37
|
+
const client = await getClient({ baseUrl, username, password, totp, ignoreSSL: (ignoreSSL == '1' || ignoreSSL == 'true') }, true);
|
|
38
38
|
if (process.env.DRDOC_DEBUG)
|
|
39
39
|
msgLog('Client: ', client);
|
|
40
40
|
|
|
41
|
-
const response = await client.signin(username, password, totp);
|
|
41
|
+
/*const response = await client.signin(username, password, totp);
|
|
42
42
|
|
|
43
43
|
if (response.HasError) {
|
|
44
44
|
msgError(`Anmeldung fehlgeschlagen: ${response.Error?.Message}`);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
msgInfo("Erfolgreich an Dr.DOC angemeldet. Die Session ist aktiv.")
|
|
48
|
+
msgInfo("Erfolgreich an Dr.DOC angemeldet. Die Session ist aktiv.");*/
|
|
49
49
|
} catch (err: any) {
|
|
50
50
|
msgError(`Fehler bei der Verbindung: ${err.message}`);
|
|
51
51
|
}
|
package/src/tools.ts
CHANGED
|
@@ -11,13 +11,27 @@ let clientInstance: DrDocClient | null = null;
|
|
|
11
11
|
*/
|
|
12
12
|
export async function getClient(config: DrDocConfig = {} as DrDocConfig, force: Boolean = false): Promise<DrDocClient> {
|
|
13
13
|
if (!clientInstance || force) {
|
|
14
|
-
|
|
14
|
+
if (process.env.DRDOC_DEBUG)
|
|
15
|
+
msgInfo('getClient: init instance');
|
|
15
16
|
clientInstance = new DrDocClient(config);
|
|
17
|
+
|
|
16
18
|
// Verbindung testen
|
|
17
|
-
if (await clientInstance.state())
|
|
18
|
-
msgInfo('
|
|
19
|
+
if (await clientInstance.state()) {
|
|
20
|
+
msgInfo('Bereits in Dr.DOC angemeldet. Die Session ist aktiv.');
|
|
21
|
+
}
|
|
19
22
|
else {
|
|
20
|
-
|
|
23
|
+
const response = await clientInstance.signin(config.username, config.password, config.totp);
|
|
24
|
+
if (response.HasError)
|
|
25
|
+
throw new Error("getClient: DrDocClient ist nicht initialisiert. Bitte vorher den Befehl /drdoc_login ausführen.");
|
|
26
|
+
|
|
27
|
+
msgInfo("Erfolgreich an Dr.DOC angemeldet. Die Session ist aktiv.");
|
|
28
|
+
|
|
29
|
+
// Verbindung testen
|
|
30
|
+
/*if (await clientInstance.state())
|
|
31
|
+
msgInfo('getClient: state ok');
|
|
32
|
+
else {
|
|
33
|
+
|
|
34
|
+
}*/
|
|
21
35
|
}
|
|
22
36
|
}
|
|
23
37
|
return clientInstance;
|
|
@@ -138,8 +152,10 @@ export const drdocTools = [
|
|
|
138
152
|
if (process.env.DRDOC_DEBUG)
|
|
139
153
|
msgLog('drdoc_properties_fields:', args);
|
|
140
154
|
return safeExecuteClient(["archive"], args, async (client, safeArgs) => {
|
|
141
|
-
const defNameArray = ['STD_AI_INVOICE_IN', 'DD_FIELD_DESC', 'STD_FIELD_DESC'];
|
|
155
|
+
const defNameArray = [process.env.DRDOC_AI_FS, 'STD_AI_INVOICE_IN', 'DD_FIELD_DESC', 'STD_FIELD_DESC'];
|
|
142
156
|
for (let defName of defNameArray) {
|
|
157
|
+
if (!defName)
|
|
158
|
+
continue;
|
|
143
159
|
const fs = await client.getFieldSelection(safeArgs.archive, "IMPORT_ASCII", defName);
|
|
144
160
|
if (process.env.DRDOC_DEBUG)
|
|
145
161
|
msgLog('props:', fs);
|
|
@@ -183,8 +199,8 @@ Beispiele für Suchoperatoren:
|
|
|
183
199
|
Datumsformat: DD.MM.YYYY
|
|
184
200
|
Zahlenformat: 0.00
|
|
185
201
|
Variablen:
|
|
186
|
-
- %DY% Variable für Datumsbereich im aktuellen/diesen Jahr
|
|
187
|
-
- %DMY% Variable für Datumsbereich im aktuellen/diesen Monat
|
|
202
|
+
- %DY% Variable für Datumsbereich im aktuellen/diesen Jahr (wird z.B. zu: *.2021)
|
|
203
|
+
- %DMY% Variable für Datumsbereich im aktuellen/diesen Monat (wird z.B. zu: *.01.2021)
|
|
188
204
|
- %DWY% Variable für Datumsbereich in der aktuellen/diesen Woche (7 Tage)
|
|
189
205
|
- %B% Variable für angemeldeten Benutzer
|
|
190
206
|
- %D% Variable für aktuelles Datum (heutiger Tag)
|