Verify bounded real AI and OSS access without dialing
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# One authorized real-provider diagnostic — 2026-10-03
|
||||
|
||||
Scope: one real AI request and one new OSS object, using synthetic test data. **No call, customer audio, carrier, real SaaS, or production acceptance.** The user authorized this bounded test; no existing object was overwritten or deleted.
|
||||
|
||||
- Existing private inputs: `.local/provider-ai.env` and `aliyun-oss.env`, both mode `0600`. Only required fields were mapped in process memory; credential values, signed URLs, object names, prompt/response text and raw provider errors were not printed or committed. These legacy files are **not** current approved SaaS task/provider snapshots or Dispatcher OSS JSON configuration.
|
||||
- **AI:** one HTTPS OpenAI-compatible Bailian `qwen-plus` request through the current `ai.Binding.Complete` SDK path, with SDK retries disabled, an explicit 16-token limit and harmless synthetic text. Passed in 0.32 s; reply length 2 bytes, SHA-256 `565339bc4d33d72817b583024112eb7f5cdf3e5eef0252d6ec1b9c9a94e12bb3`. This checks real LLM credentials and connectivity only; it does **not** verify ASR, TTS, their compatibility with the current approved provider schema, or an actual call.
|
||||
- **OSS:** one HTTPS presigned PUT using the existing official OSS v2 signer and Agent uploader. A cryptographically unique key under the isolated integration-test prefix prevented replacement of any previous object. The synthetic 27,648-byte payload was accepted, and the uploader confirmed local SHA-256 `c6fce42774195e84f761abfbb0d8cbb6a94c7a00d85479cd170faf819f6c22e2`. The test object is retained; no GET, deletion, real recording, or SaaS receipt was claimed. The test has a 45-second deadline and does not blindly retry an uncertain PUT.
|
||||
- `make check` passed; business unit coverage **70.5%**. Its Mock checks do **not** run these separately opted-in external requests. Current real-call entry remains Mock-only, the current test host lacks tcpdump and ARI/HTTP configuration, and the required capture gate still forbids dialing. Historical `agent --call-once` and its ARI runtime were removed; this diagnostic does not restore them.
|
||||
@@ -0,0 +1,47 @@
|
||||
package ai
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.ipao.vip/rogee/go-sip/internal/configread"
|
||||
)
|
||||
|
||||
// This opt-in diagnostic checks one real provider SDK request. It is not a
|
||||
// business call, an approved SaaS task, or evidence of ASR/TTS availability.
|
||||
func TestRealBailianDiagnosticOnce(t *testing.T) {
|
||||
if os.Getenv("AGENT_CALL_REAL_AI_INTEGRATION") != "1" {
|
||||
t.Skip("real AI diagnostic requires explicit opt-in")
|
||||
}
|
||||
endpoint := os.Getenv("BAILIAN_BASE_URL")
|
||||
credential := os.Getenv("BAILIAN_API_KEY")
|
||||
parsed, err := url.Parse(endpoint)
|
||||
if err != nil || parsed.Scheme != "https" || parsed.Host == "" || parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" || credential == "" {
|
||||
t.Fatal("real AI diagnostic requires a private API key and plain HTTPS endpoint")
|
||||
}
|
||||
maxTokens := int64(16)
|
||||
temperature := 0.0
|
||||
bound := Binding{
|
||||
Mode: "full_ai",
|
||||
Prompt: "This is a harmless connectivity test. Respond briefly.",
|
||||
LLM: &LLMConfig{
|
||||
Provider: configread.Provider{Endpoint: endpoint, Credential: credential},
|
||||
Model: "qwen-plus", Temperature: &temperature, MaxTokens: &maxTokens, Timeout: 30 * time.Second,
|
||||
},
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
|
||||
defer cancel()
|
||||
reply, err := bound.Complete(ctx, "Respond with OK.")
|
||||
if err != nil {
|
||||
t.Fatalf("real AI diagnostic failed: type=%T error_sha256=%x", err, sha256.Sum256([]byte(err.Error())))
|
||||
}
|
||||
if strings.TrimSpace(reply) == "" {
|
||||
t.Fatal("real AI diagnostic returned no text")
|
||||
}
|
||||
t.Logf("real LLM response: bytes=%d sha256=%x", len(reply), sha256.Sum256([]byte(reply)))
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package oss_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -29,15 +31,18 @@ func TestAlibabaOSSGrantPutIntegration(t *testing.T) {
|
||||
}
|
||||
client, err := ossclient.NewClient(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatal("OSS integration configuration is invalid")
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
payload := []byte(strings.Repeat("agent-call-oss-integration\n", 1024))
|
||||
digest := sha256.Sum256(payload)
|
||||
checksum := hex.EncodeToString(digest[:])
|
||||
objectKey := "agent-call/integration-tests/" + checksum + ".txt"
|
||||
grant, err := client.Grant(context.Background(), "integration-"+checksum[:16], objectKey, checksum, int64(len(payload)), time.Now())
|
||||
uniqueID := "integration-" + rand.Text()
|
||||
objectKey := config.KeyPrefix + "/" + uniqueID + "-" + checksum[:16] + ".txt"
|
||||
grant, err := client.Grant(ctx, uniqueID, objectKey, checksum, int64(len(payload)), time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("OSS presign failed: type=%T error_sha256=%x", err, sha256.Sum256([]byte(err.Error())))
|
||||
}
|
||||
file, err := os.CreateTemp(t.TempDir(), "oss-upload-*.txt")
|
||||
if err != nil {
|
||||
@@ -51,22 +56,15 @@ func TestAlibabaOSSGrantPutIntegration(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
uploader := agent.UploadClient{Now: time.Now, AllowedHosts: map[string]struct{}{}}
|
||||
result, err := uploader.UploadFile(context.Background(), grant, file.Name())
|
||||
result, err := uploader.UploadFile(ctx, grant, file.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("upload failed without exposing the presigned URL: %s", redactError(err, config.AccessKeyID))
|
||||
var httpErr *agent.UploadHTTPError
|
||||
if errors.As(err, &httpErr) {
|
||||
t.Fatalf("OSS PUT failed: HTTP %d", httpErr.StatusCode)
|
||||
}
|
||||
t.Fatalf("OSS PUT failed: type=%T error_sha256=%x", err, sha256.Sum256([]byte(err.Error())))
|
||||
}
|
||||
if result.SizeBytes != int64(len(payload)) || !strings.EqualFold(result.SHA256, checksum) {
|
||||
t.Fatalf("upload result mismatch: %+v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func redactError(err error, accessKeyID string) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
message := err.Error()
|
||||
if accessKeyID != "" {
|
||||
message = strings.ReplaceAll(message, accessKeyID, "<access-key-id>")
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user